Поиск подстроки в строке — различия между версиями
(→Ссылки) |
м (rollbackEdits.php mass rollback) |
||
(не показано 28 промежуточных версий 8 участников) | |||
Строка 1: | Строка 1: | ||
− | + | '''Поиск подстроки в строке''' (англ. ''String searching algorithm'') — класс алгоритмов над строками, которые позволяют найти паттерн (''pattern'') в тексте (''text''). | |
== Классификация алгоритмов поиска подстроки в строке == | == Классификация алгоритмов поиска подстроки в строке == | ||
=== Сравнение — «чёрный ящик» === | === Сравнение — «чёрный ящик» === | ||
− | Во всех алгоритмах этого типа сравнение является «чёрным ящиком» для программиста. | + | Во всех алгоритмах этого типа сравнение является «чёрным ящиком» для программиста. |
− | * | + | |
− | * | + | Преимущества: |
+ | * позволяет использовать стандартные функции сравнения участков памяти (man *cmp(3)), которые, зачастую, оптимизированы под конкретное железо. | ||
+ | |||
+ | Недостатки: | ||
+ | * не выдается точка, в которой произошло несовпадение. | ||
=== По порядку сравнения паттерна в тексте === | === По порядку сравнения паттерна в тексте === | ||
+ | ==== Прямой ==== | ||
− | + | Преимущества: | |
− | * | + | * отсутствие регрессии на «плохих» данных. |
− | * | + | |
+ | Недостатки: | ||
+ | * не самая хорошая средняя асимптотическая сложность. | ||
==== Обратный ==== | ==== Обратный ==== | ||
− | Паттерн движется по тексту слева | + | Паттерн движется по тексту слева направо, но сравнение подстрок происходит справа налево. |
− | * | + | |
+ | Преимущества: | ||
+ | * при несовпадении позволяет перемещать паттерн по строке сразу на несколько символов. | ||
+ | |||
+ | Недостатки: | ||
+ | * производительность сильно зависит от данных. | ||
==== Сравнение в необычном порядке ==== | ==== Сравнение в необычном порядке ==== | ||
− | Специфические алгоритмы, основанные, как правило, на некоторых эмпирических наблюдениях над словарём. | + | Специфические алгоритмы, основанные, как правило, на некоторых эмпирических наблюдениях над словарём.<ref>Например, [[Wikipedia:en:Raita Algorithm| Алгоритм Райты (англ.)]]</ref> |
=== По количеству поисковых шаблонов === | === По количеству поисковых шаблонов === | ||
− | + | Сколько поисковых шаблонов может обработать алгоритм за один раз. | |
− | + | ||
− | + | * один шаблон (англ. ''single pattern algorithms'') | |
+ | * конечное количество шаблонов (англ. ''finite set of patterns'') | ||
+ | * бесконечное количество шаблонов (англ. ''infinite number of patterns'') (см. [[Теория формальных языков]]) | ||
=== По необходимости препроцессинга текста === | === По необходимости препроцессинга текста === | ||
Строка 32: | Строка 46: | ||
*[[Z-функция]] | *[[Z-функция]] | ||
*[[Бор]] | *[[Бор]] | ||
− | *[[ | + | *[[Суффиксный массив]] |
− | Алгоритмы использующие препроцессинг — одни из самых быстрых в этом классе. | + | Алгоритмы, использующие препроцессинг — одни из самых быстрых в этом классе. |
== Сравнение алгоритмов == | == Сравнение алгоритмов == | ||
*<tex>|\Sigma| = \sigma</tex> — размер алфавита | *<tex>|\Sigma| = \sigma</tex> — размер алфавита | ||
− | *<tex>| | + | *<tex>|text| = t</tex> — длина текста |
− | *<tex>| | + | *<tex>|pattern| = p</tex> — длина паттерна |
*<tex>a</tex> — размер ответа(кол-во пар) | *<tex>a</tex> — размер ответа(кол-во пар) | ||
− | *<tex>m</tex> — суммарная длина | + | *<tex>m</tex> — суммарная длина всех паттернов |
{|class="wikitable" | {|class="wikitable" | ||
|+ | |+ | ||
− | !width="25%"|Название !! width="5%"| Среднее !! width="5%"| Худшее !! width="5%"| | + | !width="25%"|Название !! width="5%"| Среднее !! width="5%"| Худшее !! width="5%"|Препроцессинг !! width="5%"| Дополнительная память !! width="10%"| Кол-во поисковых шаблонов !! width="10%"| Порядок сравнения !! width="35%"| Описание |
|- align = "center" | |- align = "center" | ||
|[[Наивный алгоритм поиска подстроки в строке| Наивный алгоритм <br>(Brute Force algorithm)]] | |[[Наивный алгоритм поиска подстроки в строке| Наивный алгоритм <br>(Brute Force algorithm)]] | ||
− | |<tex>O( | + | |<tex>O(p \cdot (t - p))</tex> |
− | |<tex>O( | + | |<tex>O(t^2)</tex> |
− | | | + | | |
|<tex>O(1)</tex> | |<tex>O(1)</tex> | ||
|Single | |Single | ||
|Прямой | |Прямой | ||
− | |Сравнение — «чёрный ящик». Если <tex> | + | |Сравнение — «чёрный ящик». Если <tex>p</tex> достаточно мало по сравнению с <tex>t</tex>, то асимптотика будет близкой к <tex>O(t)</tex>, что позволяет использовать его на практике в случаях, когда паттерн много меньше текста (например, Ctrl+F в браузерах) |
− | |- align = "center" | + | |-align = "center" |
− | |[ | + | |[[Z-функция| Поиск подстроки в строке с помощью Z-функции]] |
− | |<tex>O( | + | |<tex>O(t)</tex> |
− | |<tex>O( | + | |<tex>O(t)</tex> |
− | | | + | |<tex>O(p + t)</tex> |
− | |<tex>O( | + | |<tex>O(p)</tex> |
|Single | |Single | ||
|Прямой | |Прямой | ||
− | | | + | | |
+ | |||
|- align = "center" | |- align = "center" | ||
|[[Поиск подстроки в строке с использованием хеширования. Алгоритм Рабина-Карпа| Алгоритм Рабина-Карпа <br>(Karp-Rabin algorithm)]] | |[[Поиск подстроки в строке с использованием хеширования. Алгоритм Рабина-Карпа| Алгоритм Рабина-Карпа <br>(Karp-Rabin algorithm)]] | ||
− | |<tex>O( | + | |<tex>O(p + t)</tex> |
− | |<tex>O( | + | |<tex>O(pt)</tex> |
− | | | + | |<tex>O(p)</tex> |
|<tex>O(1)</tex> | |<tex>O(1)</tex> | ||
|Single / Finite | |Single / Finite | ||
|Прямой | |Прямой | ||
− | |Данный алгоритм использует хэширование, что снижает скорость в среднем. Можно модифицировать для поиска нескольких паттернов | + | |Данный алгоритм использует хэширование, что снижает скорость в среднем. Можно модифицировать для поиска нескольких паттернов |
|- align = "center" | |- align = "center" | ||
|[[Алгоритм Кнута-Морриса-Пратта| Алгоритм Кнута-Морриса-Пратта <br>(Knuth-Morris-Pratt algorith)]] | |[[Алгоритм Кнута-Морриса-Пратта| Алгоритм Кнута-Морриса-Пратта <br>(Knuth-Morris-Pratt algorith)]] | ||
− | |<tex>O( | + | |<tex>O(p + t)</tex> |
− | |<tex>O( | + | |<tex>O(p + t)</tex> |
− | | | + | |<tex>O(p)</tex> |
− | |<tex>O( | + | |<tex>O(p)</tex> |
|Single | |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" | |- align = "center" | ||
|[[Алгоритм Ахо-Корасик| Алгоритм Ахо-Корасик <br>(Aho–Corasick string matching algorithm)]] | |[[Алгоритм Ахо-Корасик| Алгоритм Ахо-Корасик <br>(Aho–Corasick string matching algorithm)]] | ||
− | |<tex>O(m + | + | |<tex>O(m + t + a)</tex> |
− | |<tex>O( | + | |<tex>O(t)</tex> |
− | | | + | |<br> <tex>O(m)</tex> |
|<tex>O(m\sigma)</tex> | |<tex>O(m\sigma)</tex> | ||
|Finite | |Finite | ||
Строка 96: | Строка 121: | ||
|-align = "center" | |-align = "center" | ||
− | |[ | + | |[[Алгоритм Shift-Or]] |
− | |<tex>O( | + | |<tex>O(t)</tex> |
− | |<tex>O( | + | |<tex>O(t \cdot \dfrac{n}{w})</tex> <br> <tex>w</tex> — размер машинного слова |
− | | | + | |<tex>O(p + \sigma)</tex> |
− | |<tex>O( | + | |<tex>O(p + \sigma)</tex> |
|Single | |Single | ||
|Прямой | |Прямой | ||
− | |Использует тот факт, что в современных процессорах битовые сдвиг и или являются атомарными. Эффективен, если | + | |Использует тот факт, что в современных процессорах битовые сдвиг и или являются атомарными. Эффективен, если <tex>p \leqslant w</tex>. Иначе деградирует и по памяти, и по сложности |
|-align = "center" | |-align = "center" | ||
|[[Алгоритм Бойера-Мура| Алгоритм Бойера-Мура <br>(Boyer-Moore algorithm)]] | |[[Алгоритм Бойера-Мура| Алгоритм Бойера-Мура <br>(Boyer-Moore algorithm)]] | ||
− | |<tex>O( | + | |<tex>O(t)</tex> |
− | |<tex>O( | + | |<tex>O(pt)</tex> |
− | | | + | |<tex>O(p + \sigma)</tex> |
− | |<tex>O( | + | |<tex>O(p + \sigma)</tex> |
|Single | |Single | ||
|Обратный | |Обратный | ||
− | |Считается наиболее быстрым из алгоритмов общего назначения. Использует эвристики. | + | |Считается наиболее быстрым из алгоритмов общего назначения. Использует эвристики. Существует большое количество оптимизаций<ref>Например, [http://www-igm.univ-mlv.fr/~lecroq/string/node15.html#SECTION00150 Турбо-алгоритм Бойера-Мура <br>(Turbo-BM algorithm)]</ref> |
|-align = "center" | |-align = "center" | ||
− | |[ | + | |[[Алгоритм поиска подстроки в строке с помощью суффиксного массива| Поиск подстроки в строке с помощью суффиксного массива <br>(Suffix array)]] |
− | |<tex>O( | + | |<tex>O(p\log t)</tex> |
− | |<tex>O( | + | |<tex>O(p\log t)</tex> |
− | | | + | |<tex>O(t)</tex> |
− | |<tex>O( | + | |<tex>O(t)</tex> |
|Single | |Single | ||
− | | | + | |Прямой |
− | | | + | |Использует [[Суффиксный массив]]. Если использовать [[Алгоритм Касаи и др.| Largest common prefix (lcp)]], то можно уменьшить асимптотику до <tex>O(p + \log t)</tex>. Суффиксный массив можно строить[[Построение суффиксного массива с помощью стандартных методов сортировки| стандартными способами]] или [[Алгоритм Карккайнена-Сандерса| алгоритмом Карккайнена-Сандерса]]. Асимптотика приведена для построения суффиксного массива с помощью алгоритма Карккайнена-Сандерса |
|-align = "center" | |-align = "center" | ||
− | |[ | + | |[[Сжатое суффиксное дерево| Поиск подстроки в строке с помощью суффиксного дерева <br>(Suffix tree)]] |
− | |<tex>O( | + | |<tex>O(p)</tex> |
− | |<tex>O( | + | |<tex>O(p)</tex> |
− | | | + | |<tex>O(t)</tex> |
− | |<tex>O( | + | |<tex>O(t)</tex> |
|Single | |Single | ||
− | | | + | |Прямой |
− | | | + | |Позволяет выполнять поиск подстроки в строке за линейное время |
− | |-align = "center" | + | |- align = "center" |
− | |[[Алгоритм | + | |[[Алгоритм Апостолико-Крочемора| Алгоритм Апостолико-Крочемора <br>( Apostolico-Crochemore algorithm)]] |
− | |<tex>O( | + | |<tex>O(t)</tex> |
− | |<tex>O( | + | |<tex>O(t)</tex> |
− | | | + | |<tex>O(p)</tex> |
− | |<tex>O( | + | |<tex>O(p)</tex> |
|Single | |Single | ||
− | | | + | |Прямой |
− | | | + | |В худшем случае выполнит <tex>\dfrac{3}{2} n</tex> сравнений. |
|} | |} | ||
− | == | + | == Примечания == |
− | *[[wikipedia:ru:Поиск_подстроки | Википедия {{---}} Поиск подстроки]] | + | |
− | * | + | <references /> |
− | + | ||
− | * http://www-igm.univ-mlv.fr/~lecroq/string/index.html — (англ.) | + | == Источники информации == |
+ | * [[wikipedia:ru:Поиск_подстроки | Википедия {{---}} Поиск подстроки]] | ||
+ | * [[Wikipedia:en:String_searching_algorithm | Википедия {{---}} String searching algorithm]] | ||
+ | * [http://www-igm.univ-mlv.fr/~lecroq/string/index.html ESMAJ] — (англ.) Большое количество разных алгоритмов поиска подстроки в строке. Многие из них в данной статье не описаны. | ||
[[Категория: Дискретная математика и алгоритмы]] | [[Категория: Дискретная математика и алгоритмы]] | ||
[[Категория: Поиск подстроки в строке]] | [[Категория: Поиск подстроки в строке]] |
Текущая версия на 19:31, 4 сентября 2022
Поиск подстроки в строке (англ. String searching algorithm) — класс алгоритмов над строками, которые позволяют найти паттерн (pattern) в тексте (text).
Содержание
Классификация алгоритмов поиска подстроки в строке
Сравнение — «чёрный ящик»
Во всех алгоритмах этого типа сравнение является «чёрным ящиком» для программиста.
Преимущества:
- позволяет использовать стандартные функции сравнения участков памяти (man *cmp(3)), которые, зачастую, оптимизированы под конкретное железо.
Недостатки:
- не выдается точка, в которой произошло несовпадение.
По порядку сравнения паттерна в тексте
Прямой
Преимущества:
- отсутствие регрессии на «плохих» данных.
Недостатки:
- не самая хорошая средняя асимптотическая сложность.
Обратный
Паттерн движется по тексту слева направо, но сравнение подстрок происходит справа налево.
Преимущества:
- при несовпадении позволяет перемещать паттерн по строке сразу на несколько символов.
Недостатки:
- производительность сильно зависит от данных.
Сравнение в необычном порядке
Специфические алгоритмы, основанные, как правило, на некоторых эмпирических наблюдениях над словарём.[1]
По количеству поисковых шаблонов
Сколько поисковых шаблонов может обработать алгоритм за один раз.
- один шаблон (англ. single pattern algorithms)
- конечное количество шаблонов (англ. finite set of patterns)
- бесконечное количество шаблонов (англ. infinite number of patterns) (см. Теория формальных языков)
По необходимости препроцессинга текста
Виды препроцессинга:
Алгоритмы, использующие препроцессинг — одни из самых быстрых в этом классе.
Сравнение алгоритмов
- — размер алфавита
- — длина текста
- — длина паттерна
- — размер ответа(кол-во пар)
- — суммарная длина всех паттернов
Название | Среднее | Худшее | Препроцессинг | Дополнительная память | Кол-во поисковых шаблонов | Порядок сравнения | Описание |
---|---|---|---|---|---|---|---|
Наивный алгоритм (Brute Force algorithm) |
Single | Прямой | Сравнение — «чёрный ящик». Если | достаточно мало по сравнению с , то асимптотика будет близкой к , что позволяет использовать его на практике в случаях, когда паттерн много меньше текста (например, Ctrl+F в браузерах)||||
Поиск подстроки в строке с помощью Z-функции | Single | Прямой | |||||
Алгоритм Рабина-Карпа (Karp-Rabin algorithm) |
Single / Finite | Прямой | Данный алгоритм использует хэширование, что снижает скорость в среднем. Можно модифицировать для поиска нескольких паттернов | ||||
Алгоритм Кнута-Морриса-Пратта (Knuth-Morris-Pratt algorith) |
Single | Прямой | Использует префикс-функцию | ||||
Алгоритм Колусси (Colussi algorithm) |
Single | Прямой / Обратный | Оптимизация Алгоритма Кнута-Морриса-Пратта использует как прямой, так и обратный обход | ||||
Алгоритм Ахо-Корасик (Aho–Corasick string matching algorithm) |
Finite | Прямой | Строит конечный автомат. Можно хранить таблицу переходов как индексный массив (array), а можно как Красно-черное дерево. В последнем случае уменьшится расход памяти, но ухудшится асимптотика | ||||
Алгоритм Shift-Or | — размер машинного слова |
Single | Прямой | Использует тот факт, что в современных процессорах битовые сдвиг и или являются атомарными. Эффективен, если | . Иначе деградирует и по памяти, и по сложности|||
Алгоритм Бойера-Мура (Boyer-Moore algorithm) |
Single | Обратный | Считается наиболее быстрым из алгоритмов общего назначения. Использует эвристики. Существует большое количество оптимизаций[2] | ||||
Поиск подстроки в строке с помощью суффиксного массива (Suffix array) |
Single | Прямой | Использует Суффиксный массив. Если использовать Largest common prefix (lcp), то можно уменьшить асимптотику до . Суффиксный массив можно строить стандартными способами или алгоритмом Карккайнена-Сандерса. Асимптотика приведена для построения суффиксного массива с помощью алгоритма Карккайнена-Сандерса | ||||
Поиск подстроки в строке с помощью суффиксного дерева (Suffix tree) |
Single | Прямой | Позволяет выполнять поиск подстроки в строке за линейное время | ||||
Алгоритм Апостолико-Крочемора ( Apostolico-Crochemore algorithm) |
Single | Прямой | В худшем случае выполнит | сравнений.
Примечания
- ↑ Например, Алгоритм Райты (англ.)
- ↑ Например, Турбо-алгоритм Бойера-Мура
(Turbo-BM algorithm)
Источники информации
- Википедия — Поиск подстроки
- Википедия — String searching algorithm
- ESMAJ — (англ.) Большое количество разных алгоритмов поиска подстроки в строке. Многие из них в данной статье не описаны.