Подтвердить что ты не робот

Алгоритм поиска нескольких совпадений строк

Я ищу предложения для эффективного алгоритма поиска всех совпадений в большом тексте. Условия поиска будут содержаться в списке и могут иметь более 1000 возможностей. Поисковые термины могут быть 1 или более слов.

Очевидно, я мог бы сделать несколько проходов в тексте, сравнивая с каждым поисковым термином. Не слишком эффективно.

Я подумал о упорядочении поисковых терминов и объединении общих подсегментов. Таким образом, я мог быстро устранить большое количество терминов. Язык - это С++, и я могу использовать boost.

Примером поисковых терминов может быть список названий компаний из списка Fortune 500.

Идеи?

4b9b3361

Ответ 1

Не изобретайте колесо

Эта проблема интенсивно изучается. Любопытно, что лучшие алгоритмы поиска ONE pattern/string не экстраполируют легко на многострочное сопоставление.

Семейство "grep" реализует многострочный поиск очень эффективным способом. Если вы можете использовать их в качестве внешних программ, сделайте это.

Если вам действительно нужно реализовать алгоритм, я думаю, что самый быстрый способ - воспроизвести то, что делает agrep (agrep превосходит в многострочном сопоставлении!). Здесь являются исходными и исполняемыми файлами.

И здесь вы найдете статью, описывающую используемые алгоритмы, теоретический фон и много информации и указателей на сопоставление строк.

Заметка: многопоточное сопоставление было в значительной степени исследовано такими людьми, как Кнут, Бойер, Мур, Баэза-Йейтс и другие. Если вам нужен очень быстрый алгоритм, не стесняйтесь стоять на широких плечах. Не изобретайте велосипед.

Ответ 2

Как и в случае с одиночными шаблонами, существует несколько алгоритмов для сопоставления нескольких шаблонов, и вам нужно будет найти тот, который лучше всего подходит для вашей цели. В документе Быстрый алгоритм для многократного поиска (архивная копия) содержит обзор большинства из них, включая Aho-Corasick (который является своего рода мульти-шаблонная версия алгоритма Кнута-Морриса-Пратта с линейной сложностью) и Commentz-Walter (комбинация Бойер-Мура и Ахо-Корасика) и представляет новую, которая использует идеи Бойер-Мура для задача сопоставления нескольких шаблонов.

Альтернативным алгоритмом, основанным на хеше, не упомянутым в этой статье, является алгоритм Rabin-Karp, который имеет худшую сложность чем другие алгоритмы, но компенсирует это, уменьшая линейный коэффициент посредством хеширования. Какой из них лучше зависит, в конечном счете, от вашего прецедента. Возможно, вам придется реализовать несколько из них и сравнить их в своем приложении, если вы хотите выбрать самый быстрый.

Ответ 3

Предполагая, что большой текст текста является статическим английским текстом, и вам нужно сопоставить целые слова, вы можете попробовать следующее (вы должны действительно уточнить, что такое "совпадение", какой текст вы смотрите и т.д. в вашем вопрос).

Сначала предварительно обработайте весь документ в Trie или DAWG.

Trie/Dawg обладает следующим свойством:

Учитывая trie/dawg и поисковый запрос длины K, вы можете в O (K) найти время, связанное со словом (или указать, нет ли совпадения).

Использование DAWG может сэкономить вам больше места по сравнению с trie. Пытается использовать тот факт, что многие слова будут иметь общий префикс, а DAWG используют общий префикс, а также общее свойство суффикса.

В trie также поддерживайте точно список позиций слова. Например, если текст

That is that and so it is.

node для последнего t в that будет иметь список {1,3}, а node для s в is будет иметь список {2,7}.

Теперь, когда вы получаете одно слово поиска, вы можете пройти trie и легко получить список совпадений для этого слова.

Если вы получаете термин поиска по нескольким словам, вы можете сделать следующее.

Пройдите три с первым словом в поисковом выражении. Получите список совпадений и вставьте в hashTable H1.

Теперь пройдитесь по trie со вторым словом в поисковом выражении. Получите список матчей. Для каждой позиции соответствия x проверьте, существует ли x-1 в HashTable H1. Если это так, добавьте x в новую хеш-таблицу H2.

Пройдите три с третьим словом, получите список матчей. Для каждой позиции соответствия y проверьте, существует ли y-1 в H3, если так добавить новую хэш-таблицу H3.

Продолжайте и далее.

В конце вы получите список совпадений для поисковой фразы, которые дают позиции последнего слова фразы.

Вы могли бы оптимизировать шаг согласования фразы, сохранив отсортированный список позиций в списке и выполнив двоичный поиск: например, например. для каждой клавиши k в H2 вы используете двоичный поиск k + 1 в отсортированном списке для поискового запроса 3 и добавляете k + 1 в H3, если найдете его и т.д.

Ответ 4

Оптимальным решением этой проблемы является использование дерева сущностей (или массив суффикса). Это по существу три всех суффиксов строки. Для текста длиной O(N) это можно построить в O(N).

Затем все k вхождения строки длины m можно оптимально ответить в O(m + k).

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

Это типичная структура данных, используемая при анализе строк ДНК, длина которых может составлять миллионы/миллиарды оснований.

См. также

  • Википедия/Дерево суффикса
  • Алгоритмы для строк, деревьев и последовательностей: информатика и вычислительная биология (Дан Гусфилд).

Ответ 5

Итак, у вас есть много поисковых запросов и вы хотите узнать, есть ли в документе какой-либо из них?

Чисто алгоритмически, вы можете сортировать все свои возможности в алфавитном порядке, присоединяться к ним с помощью труб и использовать их в качестве регулярного выражения, если механизм регулярных выражений будет смотреть на /ant|ape/ и правильно закорачивать a в "обезьяне", если он не нашел его в "ant". Если нет, вы можете сделать "прекомпиляцию" регулярного выражения и "смять" результаты до их минимального совпадения. То есть в приведенном выше случае /a(nt|pe)/ и т.д., рекурсивно для каждой буквы.

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

Вы можете сделать это с помощью своих условий поиска, чтобы сделать гипер-быстрый "соответствует ли это слово чему-либо в моем списке условий поиска", если ваши поисковые термины имеют большой размер.

Теоретически вы также можете сделать обратное - упакуйте свой документ в дерево и затем используйте условия поиска на нем - если ваш документ статичен, а условия поиска сильно меняются.

В зависимости от того, какая оптимизация вам нужна...

Ответ 6

Являются ли слова поисковых терминов, которые вы ищете, или могут ли они быть полными датами?

Если это только слова, я бы предложил создать Red-Black Tree из всех слов, а затем искать каждое слово в дерево.

Если это могут быть отсылки, тогда это может быть намного сложнее... (?)