Каталог решений - Нечёткий поиск. Bitap алгоритм, модификация от Wu-Manber

Нечёткий поиск. Bitap алгоритм, модификация от Wu-Manber

Нечёткий поиск. Bitap алгоритм, модификация от Wu-Manber

В наличии

Временами нужен нечёткий поиск в тексте, но не всегда можно использовать внешние компоненты. Данный алгоритм прост, достаточно быстр.

Категория:

Описание

Подробное описание  алгоритма здесь. Для эмуляции битовых операций использовалась эта публикация. Код можно выполнять и на сервере и на клиенте. Попутно вычисляет расстояние Левенштейна.

Использовалась эмуляция, а не сами битовые операции, так как эмуляция может работать на гораздо бОльших текстах и гораздо быстрее.

функция ПобитовоеУмножение(Число1,Число2,ФорматнаяСтрока)
	возврат СтрЗаменить(СтрЗаменить(Формат(Число(Число1) + Число(Число2), ФорматнаяСтрока), "1", "0"), "2", "1");
КонецФункции

функция ПобитовоеСложение(Число1,Число2,ФорматнаяСтрока)
	возврат СтрЗаменить(Формат(Число(Число1) + Число(Число2), ФорматнаяСтрока), "2", "1");
КонецФункции

функция СдвигВПраво(Число1,n)
	возврат "1" + лев(Число1,n-1);
КонецФункции

функция АлгоритмНечеткогоПоиска(Текст,СтрокаПоиска) экспорт
	m = СтрДлина(Текст);
	n = СтрДлина(СтрокаПоиска);
	//для формирования нулевого битового вектора нужной длины
	ФорматнаяСтрока = "ЧЦ="+формат(n,"ЧГ=0")+"; ЧН=; ЧВН=; ЧГ=0";
	//заполнение вспомогательных битовых векторов на каждый символ строки поиска
	U = новый Соответствие;
	для i = 1 по n цикл                  
		ключ = сред(СтрокаПоиска,i,1);
		БитовыйВектор = U.Получить(ключ);
		если БитовыйВектор = Неопределено тогда
			БитовыйВектор = формат(0,ФорматнаяСтрока);	  			
		КонецЕсли;
		БитовыйВектор = лев(БитовыйВектор,i-1) + "1"+прав(БитовыйВектор,n-i);
		U.Вставить(ключ,БитовыйВектор);
	КонецЦикла;
	МассивНоваяПопытка = новый Массив(m);	
	//макс расстояние Левенштейна
	МаксОшибка = макс(2,цел(СтрДлина(СтрокаПоиска)/10));
	Для Ошибка = 0 по МаксОшибка цикл
		M1 = формат(0,ФорматнаяСтрока);		
		МассивПредыдущаяПопытка = новый массив;
		Для каждого стр из МассивНоваяПопытка цикл
			МассивПредыдущаяПопытка.Добавить(стр);
		КонецЦикла;
		для j = 1 по m цикл              
			БитовыйВектор = U.Получить(сред(Текст,j,1));
			Если БитовыйВектор = Неопределено тогда
				БитовыйВектор = формат(0,ФорматнаяСтрока);
			КонецЕсли;
			УмножениеСВектором = ПобитовоеУмножение(СдвигВПраво(M1,n),БитовыйВектор,ФорматнаяСтрока);
			Если Ошибка = 0 тогда
				ПредыдущаяПопыткаj_1 = формат(0,ФорматнаяСтрока);	
			иначеЕсли j = 1 тогда
				ПредыдущаяПопыткаj_1 = формат(0,ФорматнаяСтрока);	
			иначе
				ПредыдущаяПопыткаj_1 = МассивПредыдущаяПопытка[j-2];					
			КонецЕсли;
			
			Если Ошибка = 0 тогда
				ПредыдущаяПопыткаj = формат(0,ФорматнаяСтрока);	
			иначе
				ПредыдущаяПопыткаj = МассивПредыдущаяПопытка[j-1];					
			КонецЕсли;
			
			вставкаM1 = ПобитовоеСложение(УмножениеСВектором,ПредыдущаяПопыткаj_1,ФорматнаяСтрока);
			УдалениеM1 = ПобитовоеСложение(УмножениеСВектором,СдвигВПраво(ПредыдущаяПопыткаj,n),ФорматнаяСтрока);
			ЗаменаM1 = ПобитовоеСложение(УмножениеСВектором,СдвигВПраво(ПредыдущаяПопыткаj_1,n),ФорматнаяСтрока);
			//результат = вставкаM1 или УдалениеM1 или ЗаменаM1
			M1 = ПобитовоеСложение(вставкаM1,УдалениеM1,ФорматнаяСтрока);
			M1 = ПобитовоеСложение(M1,ЗаменаM1,ФорматнаяСтрока);
			МассивНоваяПопытка[j-1] = M1;
			Если прав(M1,1)="1" тогда
				//найденная позиция - последний символ подстроки в тесте
				//так как длина подстроки и строки поиска может быть разной, 
				//то ищем где первые ошибка+1 бит = 1, остальные 0
				СтрокаДляСравнения = формат(0,"ЧЦ="+формат(Ошибка+1,"ЧГ=0")+"; ЧН=; ЧВН=; ЧГ=0") ;
				СтрокаДляСравнения = СтрЗаменить(СтрокаДляСравнения,"0","1");
				СтрокаДляСравнения = СтрокаДляСравнения + формат(0,"ЧЦ="+формат(n-Ошибка-1,"ЧГ=0")+"; ЧН=; ЧВН=; ЧГ=0");
				Для Инт = -(j-1) по 0 цикл					
					Если МассивНоваяПопытка[-Инт] = СтрокаДляСравнения тогда
						Прервать;
					КонецЕсли;
				КонецЦикла;
				возврат(новый Структура("Слово,позиция,ошибок",Сред(Текст,-Инт+1,j+Инт),-Инт+1,Ошибка));
			КонецЕсли;
		КонецЦикла;
	КонецЦикла;
	возврат(новый Структура("Слово,позиция,ошибок","",0,0));
КонецФункции

 

has been added to your cart:
Оформление заказа