Изменения

Перейти к: навигация, поиск

Поиск подстроки в строке

4919 байт добавлено, 05:10, 27 мая 2018
Сравнение алгоритмов
'''Поиск подстроки в строке''' (англ. ''String searching algorithm'') — класс алгоритмов над строками, которые позволяют найти паттерн (''needlepattern'') в тексте (''haystacktext'').
== Классификация алгоритмов поиска подстроки в строке ==
=== Сравнение — «чёрный ящик» ===
Во всех алгоритмах этого типа сравнение является черным ящиком «чёрным ящиком» для программиста.  Преимущества:* + Позволяет позволяет использовать стандартные функции сравнения участков памяти (man *cmp(3)), которые, зачастую, оптимизированы под конкретное железо.  Недостатки:* - Не не выдается точка, в которой произошло несовпадение.
=== По порядку сравнения паттерна в тексте ===
==== Прямой ====
 
Преимущества:
* отсутствие регрессии на «плохих» данных.
==== Прямой ====Недостатки:* + Отсутсвие регрессии на «плохих» данных.* - Не не самая хорошая средняя ассимптотическая асимптотическая сложность.
==== Обратный ====
Паттерн движется по тексту слева на правонаправо, но сравнение подстрок происходит с права на левосправа налевоПреимущества:* + При при несовпадении позволяет перемещать паттерн по строке сразу на несколько символов. Недостатки:* производительность сильно зависит от данных.
==== Сравнение в необычном порядке ====
Специфические алгоритмы, основанные, как правило, на некоторых эмпирических наблюдениях над словарём. <ref>Например, [[Wikipedia:en:Raita Algorithm| Алгоритм Райты (англ.)]]</ref>
=== По количеству поисковых шаблонов ===
#Один Сколько поисковых шаблонов может обработать алгоритм за один раз. * один шаблон (англ. ''Single single pattern algorithms'')#Конечное * конечное количество шаблонов (англ. ''finite set of patterns'')#Бесконечное * бесконечное количество шаблонов (Регулярные грамматики/regexpангл. ''infinite number of patterns'ы') (см. [[Теория формальных языков]])
=== По необходимости препроцессинга текста ===
*[[Z-функция]]
*[[Бор]]
*[[Суффиксный_массивСуффиксный массив]]
Алгоритмы, использующие препроцессинг — одни из самых быстрых в этом классе.
== Сравнение алгоритмов ==
*<tex>|\Sigma| = \sigma</tex>­ — размер алфавита
*<tex>|haystacktext| = ht</tex> — длина текста*<tex>|needlepattern| = np</tex> — длина паттерна
*<tex>a</tex> — размер ответа(кол-во пар)
*<tex>m</tex> — суммарная длина всх всех паттернов
{|class="wikitable"
|+
!width="25%"|Название !! width="85%"| Среднее !! width="85%"| Худшее !! width="85%"|Необходимость препроцессинга Препроцессинг !! width="85%"| Дополнительная память !! width="10%"| Кол-во поисковых шаблонов !! width="10%"| Порядок сравнения !! width="35%"| Описание
|- align = "center"
|[[Наивный алгоритм поиска подстроки в строке| Наивный алгоритм <br>(Brute Force algorithm)]]
|<tex>O(n p \cdot (h t - np))</tex>|<tex>O(nt^2)</tex>|Нет
|<tex>O(1)</tex>
|Single
|Прямой
|Сравнение — «чёрный ящик». Если <tex>np</tex> достаточно мало по сравнению с <tex>ht</tex>, то ассимптотика асимптотика будет близкой к <tex>O(ht)</tex>, что позволяет использовать его на практике в случаях, когда паттерн много меньше текста (например, ctrlCtrl+F в браузерах)
|- align = "center"|[http://www-igm.univ[Z-mlv.fr/~lecroq/string/node18.html#SECTION00180функция| Алгоритм БойераПоиск подстроки в строке с помощью Z-Мура-Хорспула <br>(Horspool algorithm)функции]]|<tex>O(nht)</tex>|<tex>O(nht)</tex>|Да <br> <tex>O(n p + \sigmat)</tex>|<tex>O(\sigmap)</tex>
|Single
|Прямой
|В самой простой реализации использует только эвристику стоп-символа и относится к алгоритмом с сравнением — «чёрным ящиком».  
|- align = "center"
|[[Поиск подстроки в строке с использованием хеширования. Алгоритм Рабина-Карпа| Алгоритм Рабина-Карпа <br>(Karp-Rabin algorithm)]]
|<tex>O(n p + ht)</tex>|<tex>O(nhpt)</tex>|Да <br> <tex>O(np)</tex>
|<tex>O(1)</tex>
|Single/ Finite
|Прямой
|Данный алгоритм использует хэширование, что снижает скорость в среднем.Можно модифицировать для поиска нескольких паттернов
|- align = "center"
|[[Алгоритм Кнута-Морриса-Пратта| Алгоритм Кнута-Морриса-Пратта <br>(Knuth-Morris-Pratt algorith)]]
|<tex>O(n p + ht)</tex>|<tex>O(n p + ht)</tex>|Да <br> <tex>O(np)</tex>|<tex>O(np)</tex>
|Single
|Прямой
|Использует [[Префикс-функция| префикс-функцию]]
 
|-align = "center"
|[[Алгоритм Колусси| Алгоритм Колусси <br>(Colussi algorithm)]]
|<tex>O(t)</tex>
|<tex>O(t)</tex>
|<tex>O(p)</tex>
|<tex>O(p)</tex>
|Single
|Прямой / Обратный
|Оптимизация [[Алгоритм Кнута-Морриса-Пратта| Алгоритма Кнута-Морриса-Пратта]] использует как прямой, так и обратный обход
|- align = "center"
|[[Алгоритм Ахо-Корасик| Алгоритм Ахо-Корасик <br>(Aho–Corasick string matching algorithm)]]
|<tex>O(m + h t + a)</tex>|<tex>O(ht)</tex>|Да <br> <tex>O(m)</tex>
|<tex>O(m\sigma)</tex>
|finiteFinite|Прямой|Строит конечный автомат. Можно хранить таблицу переходов как индексный массив (array), а можно как [[Красно-черное дерево]]. В последнем случае уменьшится расход памяти, но ухудшится асимптотика |-align = "center"|[[Алгоритм Shift-Or]]|<tex>O(t)</tex>|<tex>O(t \cdot \dfrac{n}{w})</tex> <br> <tex>w</tex> — размер машинного слова|<tex>O(p + \sigma)</tex>|<tex>O(p + \sigma)</tex>|Single|Прямой|Использует тот факт, что в современных процессорах битовые сдвиг и или являются атомарными. Эффективен, если <tex>p \leqslant w</tex>. Иначе деградирует и по памяти, и по сложности |-align = "center"|[[Алгоритм Бойера-Мура| Алгоритм Бойера-Мура <br>(Boyer-Moore algorithm)]]|<tex>O(t)</tex>|<tex>O(pt)</tex>|<tex>O(p + \sigma)</tex>|<tex>O(p + \sigma)</tex>|Single|Обратный|Считается наиболее быстрым из алгоритмов общего назначения. Использует эвристики. Существует большое количество оптимизаций<ref>Например, [http://www-igm.univ-mlv.fr/~lecroq/string/node15.html#SECTION00150 Турбо-алгоритм Бойера-Мура <br>(Turbo-BM algorithm)]</ref> |-align = "center"|[[Алгоритм поиска подстроки в строке с помощью суффиксного массива| Поиск подстроки в строке с помощью суффиксного массива <br>(Suffix array)]]|<tex>O(p\log t)</tex>|<tex>O(p\log t)</tex>|<tex>O(t)</tex>|<tex>O(t)</tex>|Single|Прямой|Использует [[Суффиксный массив]]. Если использовать [[Алгоритм Касаи и др.| Largest common prefix (lcp)]], то можно уменьшить асимптотику до <tex>O(p + \log t)</tex>. Суффиксный массив можно строить[[Построение суффиксного массива с помощью стандартных методов сортировки| стандартными способами]] или [[Алгоритм Карккайнена-Сандерса| алгоритмом Карккайнена-Сандерса]]. Асимптотика приведена для построения суффиксного массива с помощью алгоритма Карккайнена-Сандерса |-align = "center"|[[Сжатое суффиксное дерево| Поиск подстроки в строке с помощью суффиксного дерева <br>(Suffix tree)]]|<tex>O(p)</tex>|<tex>O(p)</tex>|<tex>O(t)</tex>|<tex>O(t)</tex>|Single|Прямой|Позволяет выполнять поиск подстроки в строке за линейное время |- align = "center"|[[Алгоритм Апостолико-Крочемора| Алгоритм Апостолико-Крочемора <br>( Apostolico-Crochemore algorithm)]]|<tex>O(t)</tex>|<tex>O(t)</tex>|<tex>O(p)</tex>|<tex>O(p)</tex>|Single
|Прямой
|Строит конечный автоматВ худшем случае выполнит <tex>\dfrac{3}{2} n</tex> сравнений.
|}
 
== Примечания ==
 
<references />
 
== Источники информации ==
* [[wikipedia:ru:Поиск_подстроки | Википедия {{---}} Поиск подстроки]]
* [[Wikipedia:en:String_searching_algorithm | Википедия {{---}} String searching algorithm]]
* [http://www-igm.univ-mlv.fr/~lecroq/string/index.html ESMAJ] — (англ.) Большое количество разных алгоритмов поиска подстроки в строке. Многие из них в данной статье не описаны.
 
[[Категория: Дискретная математика и алгоритмы]]
[[Категория: Поиск подстроки в строке]]
Анонимный участник

Навигация