Главная страница


ru.algorithms

 
 - RU.ALGORITHMS ----------------------------------------------------------------
 From : Yuri Burger                          2:5020/400     30 May 2003  14:28:30
 To : Alex Astafiev
 Subject : Re: Hечеткое сравнение строк
 -------------------------------------------------------------------------------- 
 
 Hello, Alex!
 You wrote to Yuri Burger on Wed, 28 May 2003 17:42:21 +0400:
 
  AA> но было неплохо сделать
  AA> 1) Пояснение алгоритма (ибо эха не C.SOURCES, а RU.ALGORITHMS)
  AA> 2) Комментарии
  AA> 3) Хотя бы описание вх/вых параметров или осмысленые имена оных.
 
     Поясняю алгоритм.
     Цель: дать оценку "похожести" двух строк [0,1]. Предполагается что одна из
 строк является "вариантом" другой, где пропущены/добавлены/исправлены некоторые
 символы. Hапрмер, алгоритм должен дать возможность выявить сходство между
 такими строками:
     123456789 и 4567
     123456789 и 123789
     123456789 и 123*45**789
     ...
 
     Решение: пусть I{}, J{} есть множества операций удаления символа в
 произвольной позиции первой (для I) и второй (для J) строки соответственно.
 Тогда, найдем такие множества I, J что посимвольное сравнение строк, полученных
 после применения всех операций из I, J, даст максимальное совпадение. В случае
 приведенных выше примеров, результатами применения операций из найденных
 множеств должны стать строки:
         123456789 и 4567  -> 456789 и 4567  (удалили 1,2,3)
         123456789 и 123789  -> 123789 и 123789  (удалили 4,5,6)
         123456789 и 123*45**789  ->  12345789 и 12345789  (удалили 5,6, и все
 *)
 
     В двух словах - происходит поиск максимального перекрытия двух строк путем
 сжатия онных (если кому понятней, то можно использовать метафору растяжения,
 тоесть добавления фиктивных элементов).
 
     Параллельное изменение обоих строк дает симметричность алгоритма, тоесть
 сравнение первой строки со второй и второй с первой даст одинаковый результат.
     Далее, остается лишь подсчитать число совпадающих позиций и разделить его
 на длину максимальной строки из исходных двух.
     Очевидно, что алгоритм должен быть рекурсивным.
     Процедура при этом распадается на 3 ветви: последовательное сравнение,
 сравнение с предварительным удалением в первой строке, сравнение с
 предварительным удалением во второй строке. Реализуется это так:
 
     процедура
 
         удаляем текущую позицию в копии первой
         строки и входим в рекурсию с новой
         первой и старой второй строками
 
         удаляем текущую позицию в копии второй
         строки и входим в рекурсию со старой
         первой и новой второй строкой
 
         сравниваем текущие позиции в старых строках
         и перемещаемся на новую позицию (цикл)
 
     В C++ моими и Sergiy Kanilo стараниями :) это выглядит так (последний
 вариант):
 
 #ifndef __FUZZYCOMPARE_H__
 #define __FUZZYCOMPARE_H__
 
 #include <algorithm>
 
 namespace fuzzy
 {
    template<typename T> int compare(T fb,T fe,T sb,T se,int d,int maxD,int
 f,int best)
    {
       while(d!=maxD&&fb!=fe&&sb!=se&&(f+std::min(fe-fb,se-sb))>best)
       {
          int of=f;
          if(*fb==*sb){best=std::max(best,++f);}
 
          T t=sb;
          best=compare(fb,fe,++t,se,d+1,maxD,of,best);
          t=fb;
          best=compare(++t,fe,sb,se,d+1,maxD,of,best);
 
          ++fb;
          ++sb;
          d=0;
       }
       return best;
    }
 
    template<typename T> double compare(const T& first,const T& second,int
 maxD=3)
    {
       size_t size=std::max(first.size(),second.size());
       return size>0 ?
 compare(first.begin(),first.end(),second.begin(),second.end(),0,maxD,0,0)*1.0/s
 ize : 0;
    }
 }
 
 #endif
 
     А используется так:
 
    std::string s1;
    std::string s2;
 
    s1="";
    s2="";
    std::cout<<s1<<" = "<<s2<<" : "<<fuzzy::compare(s1,s2)<<std::endl;
    s1="йцукен";
    s2="йцукен";
    std::cout<<s1<<" = "<<s2<<" : "<<fuzzy::compare(s1,s2)<<std::endl;
    std::cout<<s2<<" = "<<s1<<" : "<<fuzzy::compare(s2,s1)<<std::endl;
    s1="цукен";
    s2="йцукен";
    std::cout<<s1<<" = "<<s2<<" : "<<fuzzy::compare(s1,s2)<<std::endl;
    std::cout<<s2<<" = "<<s1<<" : "<<fuzzy::compare(s2,s1)<<std::endl;
 With best regards, Yuri Burger aka J.O. Kruger.  E-mail: jo_kruger@mail.ru
 --- ifmail v.2.15dev5
  * Origin: Unknown (2:5020/400)
 
 

Вернуться к списку тем, сортированных по: возрастание даты  уменьшение даты  тема  автор 

 Тема:    Автор:    Дата:  
 Hечеткое сравнение строк   Yuri Burger   27 May 2003 09:34:19 
 Hечеткое сравнение строк   Andrew Kirillov   27 May 2003 16:47:47 
 Re: Hечеткое сравнение строк   Sergiy Kanilo   27 May 2003 22:19:51 
 Re: Hечеткое сравнение строк   Yuri Burger   28 May 2003 15:25:04 
 Re: Hечеткое сравнение строк   Sergiy Kanilo   28 May 2003 21:57:33 
 Re: Hечеткое сравнение строк   Yuri Burger   29 May 2003 12:00:21 
 Re: Hечеткое сравнение строк   Sergiy Kanilo   29 May 2003 18:01:43 
 Hечеткое сравнение строк   Alex Astafiev   28 May 2003 17:42:21 
 Re: Hечеткое сравнение строк   Yuri Burger   30 May 2003 14:28:30 
 Re: Hечеткое сравнение строк   Yuri Burger   30 May 2003 14:40:15 
 Hечеткое сравнение строк   Anton Maydell   30 May 2003 16:15:03 
 Re: Hечеткое сравнение строк   Sergey Andrianov   09 Jun 2003 22:20:02 
 Re: Hечеткое сравнение строк   Oleg Khovayko [SPAM trap - don\'t re   31 May 2003 05:01:56 
Архивное /ru.algorithms/91385e47ca8e.html, оценка 2 из 5, голосов 10
Яндекс.Метрика
Valid HTML 4.01 Transitional