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

01.04.19

Разработка - Математика и алгоритмы

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

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

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

функция ПобитовоеУмножение(Число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));
КонецФункции

 

v8 нечеткий поиск алгоритмы программирование

См. также

Метод Дугласа-Пойкера для эффективного хранения метрик

Математика и алгоритмы Платформа 1C v8.2 Конфигурации 1cv8 Россия Абонемент ($m)

На написание данной работы меня вдохновила работа @glassman «Переход на ClickHouse для анализа метрик». Автор анализирует большой объем данных, много миллионов строк, и убедительно доказывает, что ClickHouse справляется лучше PostgreSQL. Я же покажу как можно сократить объем данных в 49.9 раз при этом: 1. Сохранить значения локальных экстремумов 2. Отклонения от реальных значений имеют наперед заданную допустимую погрешность.

1 стартмани

30.01.2024    1889    stopa85    12    

34

Алгоритм симплекс-метода для решения задачи раскроя

Математика и алгоритмы Бесплатно (free)

Разработка алгоритма, построенного на модели симплекс-метода, для нахождения оптимального раскроя.

19.10.2023    4694    user1959478    50    

34

Регулярные выражения на 1С

Математика и алгоритмы Инструментарий разработчика Платформа 1С v8.3 Мобильная платформа Россия Абонемент ($m)

Что ж... лучше поздно, чем никогда. Подсистема 1С для работы с регулярными выражениями: разбор выражения, проверка на соответствие шаблону, поиск вхождений в тексте.

1 стартмани

09.06.2023    7700    4    SpaceOfMyHead    17    

56

Мини-обзор разных решений задач

Математика и алгоритмы Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Три задачи - три идеи - три решения. Мало кода, много смысла. Мини-статья.

03.04.2023    3119    RustIG    6    

25

Модель распределения суммы по базе

Математика и алгоритмы Платформа 1С v8.3 Россия Абонемент ($m)

Обычно под распределением понимают определение сумм пропорционально коэффициентам. Предлагаю включить сюда также распределение по порядку (FIFO, LIFO) и повысить уровень размерности до 2-х. 1-ое означает, что распределение может быть не только пропорциональным, но и по порядку, а 2-ое - это вариант реализации матричного распределения: по строкам и столбцам. Возможно вас заинтересует также необычное решение этой задачи через создание DSL на базе реализации текучего интерфейса

1 стартмани

21.03.2022    7955    7    kalyaka    11    

44

Изменения формата файлов конфигурации (CF) в 8.3.16

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Дополнение по формату файлов конфигурации (*.cf) в версии 8.3.16.

16.12.2021    4570    fishca    13    

37

Интересная задача на Yandex cup 2021

Математика и алгоритмы Бесплатно (free)

Мое решение задачи на Yandex cup 2021 (frontend). Лабиринт. JavaScript.

12.10.2021    8959    John_d    73    

46
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. user-z99999 67 01.04.19 20:02 Сейчас в теме
Как насчет скорости работы?
Проверяли, например на 1 млн.записей?
CyberCerber; kraynev-navi; +2 Ответить
2. trim89 107 02.04.19 03:55 Сейчас в теме
(1) Причем тут записи, если это поиск в тексте? Естественно циклом проходить записи и смотреть по каждой - это жутко долго. Этот алгоритм без индексации, в такой задаче его нерационально использовать.

По скорости. Взял текст 2000 символов, искал слово 13 символов, с 2 ошибкам. Находит за 3 секунды. Естественно, искомое слово было в самом конце текста, так что это максимальное время.
Трактор; +1 Ответить
3. MaxxiMiliSan 252 02.04.19 11:26 Сейчас в теме
1с очень медленно работает с текстом. возможно нужно было оформить это в качестве вк.
4. trim89 107 02.04.19 11:31 Сейчас в теме
(3) Ключевое, что не всегда удобно вк использовать. Да и зачем своё городить, когда уже готовые есть.
5. MaxxiMiliSan 252 02.04.19 11:37 Сейчас в теме
(4) Подскажите, правильно ли я понимаю, что поиск только для цифр?
8. trim89 107 02.04.19 15:03 Сейчас в теме
6. YanTsys 12 02.04.19 13:08 Сейчас в теме
на гораздо бОльших текстах

Для неграмотных?
7. mikl79 118 02.04.19 14:16 Сейчас в теме
9. BackinSoda 04.04.19 15:26 Сейчас в теме
Без примера поиска не разобраться
10. trim89 107 05.04.19 01:54 Сейчас в теме
(9) На просторах интернета есть подробные описания, для понятия самой идеи вполне достаточно.
Оставьте свое сообщение