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

Автор: Смирнов М.В.
Оценка алгоритмов сходства строковых переменных методом зеркального регулярного выражения
Аннотация

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

Одной из наиболее востребованных функций в системах поиска текста является функция сравнения двух строк [1]. Судя по постам и публикациям, многие программисты отдают предпочтение алгоритму Левенштейна, который обеспечивает реализацию нечеткого поиска, т.е. поиска при не строгом задании поисковой фразы [2,3,7]. Не последнюю роль в выборе функции Левенштейна играет наличие соответствующей подпрограммы levenshtein() на языке PHP [4]. Метрика или расстояние Левенштейна представляет собой минимальное количество (целое число) операций вставки, удаления и замены одного символа на другой, необходимых для превращения одной строки в другую. Так же нужно отметить еще одну подпрограмму в спецификации функций PHP, функцию similar_text(), которая находит степень похожести двух строк по алгоритму Оливера (Oliver). В алгоритме Oliver на PHP производится поиск количества общих символов в сравниваемых строках. Подпрограмма similar_text() возвращает численное значение похожести двух строк в процентах [5].

Автор настоящей статьи использовал названные подпрограммы (и ряд других) при формировании семантического ядра много-страничных сайтов в целях SEO-оптимизации под поисковые запросы [11]. Проблема автоматизированного подбора уникальных или квази-уникальных названий в семантике сайтов (интернет магазинов) известна. Основной недостаток подпрограмм levenshtein() и similar_text() состоит в чуствительности к перестановке слов в сравниваемых фразах. Рассмотрим реальный пример. В качестве первой строки будем использовать фразу «художественная резьба по камню», а во второй строке сделаем перестановку слов без их изменения – «резьба по камню художественная». Результат применения функции similar_text() составил значение похожести – 49.12%, а возвращаемое значение функции levenshtein() составило значение 38, что соответствует в относительной мере к длине строк – 29.63%.

С последней проблемой неплохо справляется алгоритм Джаккарда. Существенным недостатком алгоритма Джаккарда является критичность к ошибкам в написании слов в сравниваемых текстах: так если в одной из строк слово «художественная» будет иметь ошибку - «художественая», результат вычисления коэффициента Джаккарда, в среднем, составляет 59%, при точности 0.1 (100 итераций) [8,10]. Как справедливо отмечено в работе [9] - "неустойчивость алгоритма Джаккарда проявляется при наличии орфографических ошибок и синонимических замен". Наиболее успешным в плане инвариантности показал себя алгоритм "Трех-Множеств" [12], который так же обеспечивает улавливание единичных ошибок. Основной недостаток алгоритма "Трех-Множеств" заключается в снижении эффективности результатов сравнения при длине текста более 200-250 символов и/или при сравнении случайного набора символов, т.е. абракадабры.

Чтобы как-то оценить возможности улучшения сходства предлагается применить зеркальное регулярное выражение (ЗРВ) для всех слов в сравниваемых строковых переменных:
  if( preg_match("/$ws1/",$ws2) || preg_match("/$ws2/",$ws1) ){  
  ........ }else{  ......}  ,
где строковые переменные $ws1 и $ws2 являются отдельными словами сравниваемых текстов. Основным вычислительным блоком программной реализации являтся двумерный вложенный массив:
  $eq=0;
  foreach($arr1 as $ws1){
  foreach($arr2 as $ws2){
              $lengws1 = strlen($ws1);
              $lengws2 = strlen($ws2);
              $deltalenws = abs($lengws1 - $lengws2);
              if( preg_match("/$ws1/",$ws2) || preg_match("/$ws2/",$ws1) ){
                                  if( $deltalenws <= $_delta_lett ){
                                                print "совпадение: $ws1 $ws2\n";  
                                                      $eq++;
                                   }
              }else{  ...алгоритм обработки несовпадения...  }
  }
  } ,
где $arr1 и $arr1 - массивы слов сравниваемых текстов, параметр $_delta_lett, используется для игнорирования совпадения слов, разность длин которых превышает $delta_lett. Алгоритм обработки несовпадения (АОН) является дополнительным при вычислении ЗРВ. Выше представленный код реализован в подпрограмме evaltextRus(). Оценка сходства, представленных выше фраз с одной ошибкой «художественая», составила значение 92.86 %. Рассматриваемый алгоритм нечувствителен (инвариантен) к перестановкам слов в сравниваемых фразах и реагирует на отдельные ошибки снижением сходства в процентах.

Скачать архив подпрограмы evaltextRus(), а также пример сравнения двух строк на PHP можно по адресу http://www.smirnov.sp.ru/cgi_java/php/evaltextrus_zip.html [6]. Если входными данными являются текстовые (строковые) переменные в кодировке UTF-8, то в этом случае длины $lengws1 и $lengws2 удваиваются и требуется их уменьшение в 2 раза:
              $lengws1 = strlen($ws1)>>1;
              $lengws2 = strlen($ws2)>>1;
В алгоритме АОН применяется посимвольное сравнение и оценка несовпадения при помощи параметра $prob75. По этому параметру игнорируется совпадение слов, если их сходство менее $prob75 % относительно длины наибольшего слова. Обычно $prob75 задается в диапазоне 0.7-0.8.

Литература:
[1] Функции сравнения строк. Справочник PHP.
[2] Расстояние Левенштейна.
[3] Применение алгоритмов нечеткого поиска в PHP
[4] Функция levenshtein(). Руководство по PHP.

[5] Функция similar_text(). Руководство по PHP.
[6] Скачать функцию evaltextRus. Вычисление зеркального регулярного выражения. Программа на PHP.
[7] Нечёткий поиск в тексте и словаре
[8] MinHash — выявляем похожие множества
[9] Н.В. Неелова, Сычугов А. А. Вычисление нечетких дублей по формуле Джаккарда с учетом синонимических замен и стоповых слов. Тула: Известия ТулГУ, 2009. К статье ..."Вычисление нечетких дублей ..."
[10] On-line вычисление коэффициента Джаккарда на JavaScript
[11] Распределение вероятностей частоты поисковых запросов

[12] Инвариантная оценка сходства двух строковых переменных методом "Трех-Множеств"