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

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
0
7 552
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

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

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

Есть описание алгоритма, который вы могли бы использовать здесь (см. Раздел 3.1).

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

Ответ принят как подходящий

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

В теории

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

На практике

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

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

Обратите внимание, что вам придется разбивать предложения, прежде чем разбивать их на слова, иначе появятся ложные n-граммы, которые пересекают границы предложения.

Gregg Lind 19.09.2008 01:08

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

Tyler 19.09.2008 06:30

Простое построение массива суффиксов O (n): springerlink.com/content/0nyb22e5amj4rac4… это решенная проблема. - Более того, даже наивный алгоритм O (n log n) довольно хорошо работает на практике.

Konrad Rudolph 30.06.2011 15:38

предположим, вам дан отсортированный массив 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).

Другие вопросы по теме