Какой алгоритм можно использовать для поиска повторяющихся фраз в строке?

Для произвольной строки какой эффективный метод поиска повторяющихся фраз? Мы можем сказать, что фразы должны быть длиннее определенной длины, чтобы быть включенными.

В идеале вы должны получить количество вхождений каждой фразы.


person Larsenal    schedule 17.09.2008    source источник


Ответы (5)


Как упоминалось ранее, дерево суффиксов — лучший инструмент для работы. Мой любимый сайт с деревьями суффиксов — http://www.allisons.org/ll/AlgDS/Tree/Suffix/. Он перечисляет все изящные способы использования деревьев суффиксов на одной странице и имеет встроенное тестовое приложение js для проверки строк и работы с примерами.

person Sridhar Iyer    schedule 17.09.2008

Теоретически

  • массив суффиксов — лучший ответ, поскольку его можно реализовать использовать линейное пространство и время для обнаружения любых повторяющихся подстрок. Однако наивная реализация на самом деле требует времени O (n ^ 2 log n) для сортировки суффиксов, и не совсем очевидно, как уменьшить это до O (n log n), не говоря уже о O (n), хотя вы можете прочитать соответствующие документы, если вы хотите.
  • дерево суффиксов может занимать немного больше памяти (хотя и остается линейным). чем массив суффиксов, но его легче реализовать для быстрой сборки, поскольку вы можете использовать что-то вроде идеи сортировки по основанию при добавлении элементов в дерево (подробности см. Википедии из названия).
  • Также полезно знать алгоритм KMP. , который специализируется на очень быстром поиске определенной подстроки в более длинной строке. Если вам нужен только этот особый случай, просто используйте KMP и не нужно сначала создавать индекс достаточностей.

На практике

Я предполагаю, что вы анализируете документ слов на естественном языке (например, английском) и действительно хотите что-то сделать с данными, которые вы собираете.

В этом случае вы можете просто выполнить быстрый анализ n-gram для некоторых небольших n, например просто n=2 или 3. Например, вы можете разбить документ на список слов, удалив знаки препинания, заглавные буквы и слова-основы (работает, работает как -> «бег»), чтобы увеличить семантические совпадения. Затем просто создайте хэш-карту (такую ​​как hash_map в C++, словарь в python и т. д.) каждой соседней пары слов с ее количеством вхождений до сих пор. В конце концов, вы получаете очень полезные данные, которые очень быстро кодируются, а не безумно медленно выполняются.

person Tyler    schedule 18.09.2008
comment
Обратите внимание, что вам придется разбивать предложения, прежде чем разбивать их на слова, иначе будут ложные n-граммы, пересекающие границы предложений. - person Gregg Lind; 19.09.2008
comment
Кажется интуитивно понятным сделать это (исключить n-граммы вместо предложений), хотя я видел некоторые работы, которые на самом деле предполагают обратное - возможно, поскольку вы все еще можете характеризовать документ в некоторой степени просто по типам переходов, используемых между предложениями. - person Tyler; 19.09.2008
comment
Простая конструкция массива суффиксов O(n): решенная проблема. – Более того, даже наивный алгоритм O(n log n) на практике работает достаточно хорошо. - person Konrad Rudolph; 30.06.2011

Суффиксные деревья — хороший способ реализовать это. Внизу этой статьи есть ссылки на реализации на разных языках.

person jmah    schedule 17.09.2008

Как сказал jmah, для этого вы можете использовать суффиксные деревья/суффиксные массивы.

Существует описание алгоритма, который вы можете использовать здесь (см. раздел 3.1).

Вы можете найти более подробное описание в книге, которую они цитируют (Gusfield, 1997), а именно в книгах Google.

person Todd Gamblin    schedule 17.09.2008

предположим, вам дан отсортированный массив A с n элементами (i=1,2,3,...,n)

Algo(A(i))
{
  while i<>n
  {
    temp=A[i];
    if A[i]<>A[i+1] then
    {     
      temp=A[i+1];
      i=i+1;
      Algo(A[i])
    }
    else if A[i]==A[i+1] then
      mark A[i] and A[i+1] as duplicates
  }
}

Этот алгоритм работает за время O(n).

person Community    schedule 24.02.2009