Поиск подстроки: различия между версиями
[непроверенная версия] | [отпатрулированная версия] |
Mercury (обсуждение | вклад) |
Celest (обсуждение | вклад) →Преамбула: перенесена на КУ |
||
(не показано 39 промежуточных версий 22 участников) | |||
Строка 1: | Строка 1: | ||
<noinclude>{{к удалению|2021-12-05}}</noinclude> |
|||
''[[Поиск информации]]'' — одно из основных использований [[компьютер]]а. Одна из простейших задач поиска информации — '''поиск точно заданной подстроки в строке'''. Тем не менее, эта задача чрезвычайно важна — она применяется в [[текстовый редактор|текстовых редакторах]], [[СУБД]], [[поисковая машина|поисковых машинах]]… |
|||
'''Поиск подстроки в строке''' — одна из простейших задач [[Поиск информации|поиска информации]]. Применяется в виде встроенной функции в [[текстовый редактор|текстовых редакторах]], [[СУБД]], [[поисковая машина|поисковых машинах]], [[язык программирования|языках программирования]] и т. п. |
|||
В задачах поиска традиционно принято обозначать шаблон поиска как ''needle'' ({{ |
В задачах поиска традиционно принято обозначать шаблон поиска как ''needle'' ({{tr-en|иголка}}), а строку, в которой ведётся поиск — как ''haystack'' ({{tr-en|[[wikt:искать иголку в стоге сена|стог сена]]}}). Также обозначим через Σ алфавит, на котором проводится поиск.{{Нет АИ|4|1|2016}} |
||
== Несостоятельность примитивного алгоритма == |
== Несостоятельность примитивного алгоритма == |
||
⚫ | |||
⚫ | |||
for i=0...|haystack|-|needle| |
for i=0...|haystack|-|needle| |
||
for j= |
for j=0...|needle| |
||
if haystack[i+j]<>needle[j] |
if haystack[i+j + 1]<>needle[j] |
||
then goto 1 |
then goto 1 |
||
output("Найдено: ", i+1) |
output("Найдено: ", i+1) |
||
1: |
1: |
||
Простейший алгоритм поиска даже в ''лучшем'' случае проводит |''haystack''| |
Простейший алгоритм поиска даже в ''лучшем'' случае проводит |''haystack''|−|''needle''|+1 сравнение; если же есть много частичных совпадений, скорость снижается до ''O''(|''haystack''|·|''needle''|). |
||
Доказано, что примитивный алгоритм отрабатывает в среднем 2''h'' сравнений<ref>[http://www-igm.univ-mlv.fr/~lecroq/string/node3.html Brute force algorithm] {{Wayback|url=http://www-igm.univ-mlv.fr/~lecroq/string/node3.html |date=20090121190217 }}{{ref-en}}</ref>. |
|||
== Для чего нужно так много алгоритмов? == |
== Для чего нужно так много алгоритмов? == |
||
На сегодняшний день существует огромное разнообразие алгоритмов поиска подстроки. Программисту приходится выбирать подходящий в зависимости от таких факторов. |
На сегодняшний день существует огромное разнообразие алгоритмов поиска подстроки. Программисту приходится выбирать подходящий в зависимости от таких факторов. |
||
# Нужна ли вообще оптимизация, или хватает примитивного алгоритма? Как правило, именно его реализуют стандартные библиотеки языков программирования. |
|||
# «Враждебность» пользователя. Другими словами: будет ли пользователь намеренно задавать данные, на которых алгоритм будет медленно работать? Существуют очень простые алгоритмы, оценка которых ''O''(|''haystack''|·|''needle''|) в худшем случае, но на «обычных» данных количество сравнений намного меньше |''haystack''|. Только в [[1990-е]] годы были созданы алгоритмы, дающие сложность ''O''(|''haystack''|) в худшем случае и меньше |''haystack''| в среднем. |
# «Враждебность» пользователя. Другими словами: будет ли пользователь намеренно задавать данные, на которых алгоритм будет медленно работать? Существуют очень простые алгоритмы, оценка которых ''O''(|''haystack''|·|''needle''|) в худшем случае, но на «обычных» данных количество сравнений намного меньше |''haystack''|. Только в [[1990-е]] годы были созданы алгоритмы, дающие сложность ''O''(|''haystack''|) в худшем случае и меньше |''haystack''| в среднем. |
||
# [[Грамматика (наука)|Грамматика]] языка может быть недружественной к тем или иным эвристикам, которые ускоряют поиск «в среднем». |
# [[Грамматика (наука)|Грамматика]] языка может быть недружественной к тем или иным эвристикам, которые ускоряют поиск «в среднем». |
||
# Архитектура процессора. Некоторые процессоры имеют [[автоинкрементная операция|автоинкрементные]] или [[SIMD]]-операции, которые позволяют быстро сравнить два участка ОЗУ (например, <code>rep cmpsd</code> на [[x86]]). На таких процессорах заманчиво применить алгоритм, который просто бы сравнивал ''needle'' с ''haystack'' — разумеется, не во всех позициях. |
# [[Архитектура процессора]]. Некоторые процессоры имеют [[автоинкрементная операция|автоинкрементные]] или [[SIMD]]-операции, которые позволяют быстро сравнить два участка ОЗУ (например, <code>rep cmpsd</code> на [[x86]]). На таких процессорах заманчиво применить алгоритм, который просто бы сравнивал ''needle'' с ''haystack'' — разумеется, не во всех позициях. |
||
# Размер алфавита. Многие алгоритмы (особенно основанные на сравнении с конца) имеют эвристики, связанные с несовпавшим символом. На больших алфавитах таблица символов будет занимать много памяти, на малых — соответствующая эвристика будет неэффективной. |
# Размер алфавита. Многие алгоритмы (особенно основанные на сравнении с конца) имеют эвристики, связанные с несовпавшим символом. На больших алфавитах таблица символов будет занимать много памяти, на малых — соответствующая эвристика будет неэффективной. |
||
# Возможность проиндексировать ''haystack''. Если таковая есть, поиск серьёзно ускорится. |
# Возможность проиндексировать ''haystack''. Если таковая есть, поиск серьёзно ускорится. |
||
# Требуется ли одновременный поиск нескольких строк? Приблизительный поиск? Побочные свойства некоторых алгоритмов ([[алгоритм Ахо-Корасик|Ахо-Корасик]], [[Двоичный алгоритм поиска подстроки|двоичного алгоритма]]) позволяют такое. |
# Требуется ли одновременный поиск нескольких строк? Приблизительный поиск? Побочные свойства некоторых алгоритмов ([[алгоритм Ахо-Корасик|Ахо-Корасик]], [[Двоичный алгоритм поиска подстроки|двоичного алгоритма]]) позволяют такое. |
||
Как правило, в [[текстовый редактор|текстовом редакторе]] достаточно взять самый простой эвристический алгоритм наподобие [[алгоритм Бойера |
Как правило, в [[текстовый редактор|текстовом редакторе]] достаточно взять самый простой эвристический алгоритм наподобие [[алгоритм Бойера — Мура — Хорспула|Бойера — Мура — Хорспула]] — даже очень медленный ПК справится с поиском за доли секунды. Если же объём текста измеряется гигабайтами, либо поиск запущен на сервере, который обрабатывает множество запросов — приходится выбирать наиболее удачный алгоритм из доступных. Например, программы [[Определение плагиата|определения плагиата]] осуществляют онлайн-проверку, используя алгоритмы поиска подстроки среди большого количества документов, хранящихся в собственной базе. |
||
== Алгоритмы == |
== Алгоритмы == |
||
Для сокращения обозначим: |
Для сокращения обозначим: |
||
* |Σ|=σ — размер алфавита. |
* |Σ|=σ — размер алфавита. |
||
Строка 39: | Строка 38: | ||
Вычислительная сложность определяется ''до первого совпадения''. '''Жирным шрифтом''' выделены важнейшие с практической точки зрения алгоритмы. |
Вычислительная сложность определяется ''до первого совпадения''. '''Жирным шрифтом''' выделены важнейшие с практической точки зрения алгоритмы. |
||
=== Основанные на сравнении как «чёрном ящике» === |
=== Основанные на сравнении как «[[Чёрный ящик|чёрном ящике]]» === |
||
⚫ | |||
⚫ | |||
К этой категории относится и примитивный алгоритм поиска. |
К этой категории относится и примитивный алгоритм поиска. |
||
Строка 60: | Строка 58: | ||
| |
| |
||
|- |
|- |
||
| '''[[Алгоритм Бойера |
| '''[[Алгоритм Бойера — Мура — Хорспула]]''' |
||
| ''O''(''n''+σ) |
| ''O''(''n''+σ) |
||
| ~ 2''H'' / σ<ref>{{Cite web |url=http://www-igm.univ-mlv.fr/~lecroq/string/node18.html#SECTION00180 |title=Horspool algorithm<!-- Заголовок добавлен ботом --> |access-date=2013-05-02 |archive-date=2012-08-29 |archive-url=https://web.archive.org/web/20120829203936/http://www-igm.univ-mlv.fr/~lecroq/string/node18.html#SECTION00180 |deadlink=no }}</ref> |
|||
⚫ | |||
| ''O''(''Hn'') |
| ''O''(''Hn'') |
||
| Упрощённый до предела алгоритм Бойера |
| Упрощённый до предела алгоритм Бойера — Мура; использует только видоизменённую эвристику стоп-символа — за стоп-символ всегда берётся символ ''haystack'', расположенный напротив последнего символа ''needle''. |
||
|- |
|- |
||
| '''[[Алгоритм быстрого поиска подстроки|Алгоритм быстрого поиска]]'''<br |
| '''[[Алгоритм быстрого поиска подстроки|Алгоритм быстрого поиска]]'''<br>[[Алгоритм Санди]] |
||
| ''O''(''n''+σ) |
| ''O''(''n''+σ) |
||
| <''H'' |
| <''H'' |
||
Строка 74: | Строка 72: | ||
=== Основанные на сравнении с начала === |
=== Основанные на сравнении с начала === |
||
Это семейство алгоритмов страдает невысокой скоростью на «хороших» данных, что компенсируется отсутствием регрессии на «плохих». |
Это семейство алгоритмов страдает невысокой скоростью на «хороших» данных, что компенсируется отсутствием регрессии на «плохих». |
||
Строка 90: | Строка 87: | ||
| <''H''+''n'' |
| <''H''+''n'' |
||
| ''O''(''Hn'') |
| ''O''(''Hn'') |
||
| [[ |
| [[Хеширование]] позволяет серьёзно снизить сложность в среднем |
||
|- |
|- |
||
| {{nobr|'''Автоматный алгоритм'''}}<br |
| {{nobr|'''Автоматный алгоритм'''}}<br>[[Алгоритм Ахо-Корасик]] |
||
| ''O''(''n''σ) |
| ''O''(''n''σ) |
||
| colspan=2 align=center | = ''H'' |
| colspan=2 align=center | = ''H'' |
||
Строка 99: | Строка 96: | ||
| '''[[Алгоритм Кнута-Морриса-Пратта]]''' |
| '''[[Алгоритм Кнута-Морриса-Пратта]]''' |
||
| ''O''(''n'') |
| ''O''(''n'') |
||
| colspan=2 align=center | |
| colspan=2 align=center | ≤ 2''H'' |
||
| Один из первых алгоритмов с линейной оценкой в худшем случае. Модификация алгоритма Ахо-Корасик, строящая автомат неявно на основе префикс-функции. |
| Один из первых алгоритмов с линейной оценкой в худшем случае. Модификация алгоритма Ахо-Корасик, строящая автомат неявно на основе префикс-функции. |
||
|- |
|- |
||
| [[Алгоритм Апостолико-Крошмора]] |
| [[Алгоритм Апостолико-Крошмора]] |
||
| ''O''(''n'') |
| ''O''(''n'') |
||
⚫ | |||
| |
|||
| |
| ≤1,5''H'' |
||
| |
| |
||
|- |
|- |
||
| '''[[Алгоритм Shift-Or]]'''<br |
| '''[[Алгоритм Shift-Or]]'''<br>[[Bitap-алгоритм]]<br>[[Двоичный алгоритм поиска подстроки|Двоичный алгоритм]] |
||
| ''O''(''n''+σ) |
| ''O''(''n''+σ) |
||
| colspan=2 align=center | {{nobr|1==''H''·[[потолок числа|ceil]](''n/w'')}} |
| colspan=2 align=center | {{nobr|1==''H''·[[потолок числа|ceil]](''n/w'')}} |
||
Строка 115: | Строка 112: | ||
=== Основанные на сравнении с конца === |
=== Основанные на сравнении с конца === |
||
В этом семействе алгоритмов ''needle'' движется по ''haystack'' слева направо, но сравнение этих строк друг с другом проводится справа налево. Сравнение справа налево позволяет в случае несовпадения сдвинуть ''needle'' не на одну позицию, а на несколько. |
В этом семействе алгоритмов ''needle'' движется по ''haystack'' слева направо, но сравнение этих строк друг с другом проводится справа налево. Сравнение справа налево позволяет в случае несовпадения сдвинуть ''needle'' не на одну позицию, а на несколько. |
||
Строка 127: | Строка 123: | ||
! макс. |
! макс. |
||
|- |
|- |
||
| '''[[Алгоритм Бойера |
| '''[[Алгоритм Бойера — Мура]]''' |
||
| ''O''(''n''+σ) |
| ''O''(''n''+σ) |
||
| <''H'' |
| <''H'' |
||
| ''O''(''Hn'') |
| ''O''(''Hn'') |
||
| Стандартный алгоритм поиска подстроки в строке. Считается наиболее эффективным алгоритмом общего назначения.<ref>{{Cite web |url=http://www-igm.univ-mlv.fr/~lecroq/string/node14.html#SECTION00140 |title=Boyer-Moore algorithm<!-- Заголовок добавлен ботом --> |access-date=2013-05-02 |archive-date=2013-02-06 |archive-url=https://web.archive.org/web/20130206123458/http://www-igm.univ-mlv.fr/~lecroq/string/node14.html#SECTION00140 |deadlink=no }}</ref> |
|||
| Стандартный алгоритм поиска подстроки в строке |
|||
|- |
|- |
||
| [[Алгоритм Чжу-Такаоки]] |
| [[Алгоритм Чжу-Такаоки]] |
||
Строка 137: | Строка 133: | ||
| <''H'' |
| <''H'' |
||
| ''O''(''Hn'') |
| ''O''(''Hn'') |
||
| Алгоритм Бойера |
| Алгоритм Бойера — Мура, оптимизированный под короткие алфавиты |
||
|- |
|- |
||
| [[Алгоритм Апостолико-Джанкарло]] |
| [[Алгоритм Апостолико-Джанкарло]] |
||
| ''O''(''n''+σ) |
| ''O''(''n''+σ) |
||
| <''H'' |
| <''H'' |
||
| |
| ≤1,5''H'' |
||
| Одна из первых попыток получить <''H'' в типичном случае и ''O''(''H'') в худшем. Очень сложен в реализации. |
| Одна из первых попыток получить <''H'' в типичном случае и ''O''(''H'') в худшем. Очень сложен в реализации. |
||
|- |
|- |
||
| [[Турбо-алгоритм Бойера |
| [[Турбо-алгоритм Бойера — Мура]] |
||
| ''O''(''n''+σ) |
| ''O''(''n''+σ) |
||
| <''H'' |
| <''H'' |
||
| |
| ≤2''H'' |
||
| Один из наиболее эффективных алгоритмов, не дающих регрессии на «плохих» данных |
| Один из наиболее эффективных алгоритмов, не дающих регрессии на «плохих» данных |
||
|} |
|} |
||
=== Проводящие сравнение в необычном порядке === |
=== Проводящие сравнение в необычном порядке === |
||
{| class="wikitable" |
{| class="wikitable" |
||
! rowspan=2 | Название |
! rowspan=2 | Название |
||
Строка 169: | Строка 164: | ||
| Простой алгоритм, сравнивающий второй символ, затем начиная с третьего в режиме «чёрного ящика», и, наконец, первый. При {{nobr|''n''[1]≠''n''[2]}}<ref>Напомним, символы нумеруются с 1, как в [[Паскаль (язык программирования)|Паскале]].</ref> и несовпадении на второй-третьей стадии — сдвиг на 2 вправо. |
| Простой алгоритм, сравнивающий второй символ, затем начиная с третьего в режиме «чёрного ящика», и, наконец, первый. При {{nobr|''n''[1]≠''n''[2]}}<ref>Напомним, символы нумеруются с 1, как в [[Паскаль (язык программирования)|Паскале]].</ref> и несовпадении на второй-третьей стадии — сдвиг на 2 вправо. |
||
|- |
|- |
||
| Алгоритм Райты<br |
| Алгоритм Райты<br>Алгоритм Бойера — Мура — Хорспула — Райты |
||
| ''O''(''n''+σ) |
| ''O''(''n''+σ) |
||
| <''H'' |
| <''H'' |
||
Строка 176: | Строка 171: | ||
|} |
|} |
||
== См. также == |
|||
{{compu-stub}} |
|||
* [[Подстрока]] |
|||
* [[Список алгоритмов#Алгоритмы на строках|Алгоритмы на строках]] |
|||
* [[Сопоставление с образцом]] |
|||
* [[Алгоритмы: построение и анализ]] |
|||
== Примечания == |
== Примечания == |
||
{{примечания}} |
{{примечания}} |
||
== |
== Литература == |
||
* {{книга |
|||
|автор = {{nobr|Гасфилд Д.}} |
|||
|заглавие = Строки, деревья и последовательности в алгоритмах: Информатика и вычислительная биология |
|||
|оригинал = Algorithms on String, Trees, and Sequences. Computer Science and Computational Biology |
|||
|ссылка = |
|||
|ответственный = Пер. с англ. И. В. Романовского |
|||
|издание = 2-е изд |
|||
|место = СПб. |
|||
|издательство = Невский Диалект |
|||
|год = 2003 |
|||
|страниц = 654 |
|||
|isbn = 5-7940-0103-8, 5-94157-321-9, 0-521-58519-8 |
|||
}} |
|||
* {{книга |
|||
|автор = {{nobr|Смит Б.}} |
|||
|заглавие = Методы и алгоритмы вычислений на строках |
|||
|оригинал = Computing Patterns in Strings |
|||
|ссылка = |
|||
|ответственный = |
|||
|издание = |
|||
|место = М. |
|||
|издательство = Вильямс |
|||
|год = 2006 |
|||
|страниц = 496 |
|||
|isbn = 5-8459-1081-1, 0-201-39839-7 |
|||
}} |
|||
* {{книга |
|||
|автор = {{nobr|Окулов С. М.}} |
|||
|заглавие = Алгоритмы обработки строк |
|||
|ссылка = |
|||
|ответственный = |
|||
|издание = |
|||
|место = М. |
|||
|издательство = Бином |
|||
|год = 2013 |
|||
|страниц = 255 |
|||
|isbn = 978-5-9963016-2-1 |
|||
}} |
|||
== Ссылки == |
|||
* [http://www-igm.univ-mlv.fr/~lecroq/string/index.html Большая подборка алгоритмов поиска подстроки]{{ref-en}} |
* [http://www-igm.univ-mlv.fr/~lecroq/string/index.html Большая подборка алгоритмов поиска подстроки]{{ref-en}} |
||
{{Строки}}{{rq|style|wikify|check}} |
|||
[[Категория:Поиск подстроки| |
[[Категория:Поиск подстроки| ]] |
Текущая версия от 11:43, 25 августа 2023
Эту статью предлагается удалить. |
Поиск подстроки в строке — одна из простейших задач поиска информации. Применяется в виде встроенной функции в текстовых редакторах, СУБД, поисковых машинах, языках программирования и т. п.
В задачах поиска традиционно принято обозначать шаблон поиска как needle (с англ. — «иголка»), а строку, в которой ведётся поиск — как haystack (с англ. — «стог сена»). Также обозначим через Σ алфавит, на котором проводится поиск.[источник не указан 3291 день]
Несостоятельность примитивного алгоритма
[править | править код]Если считать, что строки нумеруются с 1, простейший алгоритм (англ. brute force algorithm, naïve algorithm) выглядит так.
for i=0...|haystack|-|needle| for j=0...|needle| if haystack[i+j + 1]<>needle[j] then goto 1 output("Найдено: ", i+1) 1:
Простейший алгоритм поиска даже в лучшем случае проводит |haystack|−|needle|+1 сравнение; если же есть много частичных совпадений, скорость снижается до O(|haystack|·|needle|).
Доказано, что примитивный алгоритм отрабатывает в среднем 2h сравнений[1].
Для чего нужно так много алгоритмов?
[править | править код]На сегодняшний день существует огромное разнообразие алгоритмов поиска подстроки. Программисту приходится выбирать подходящий в зависимости от таких факторов.
- Нужна ли вообще оптимизация, или хватает примитивного алгоритма? Как правило, именно его реализуют стандартные библиотеки языков программирования.
- «Враждебность» пользователя. Другими словами: будет ли пользователь намеренно задавать данные, на которых алгоритм будет медленно работать? Существуют очень простые алгоритмы, оценка которых O(|haystack|·|needle|) в худшем случае, но на «обычных» данных количество сравнений намного меньше |haystack|. Только в 1990-е годы были созданы алгоритмы, дающие сложность O(|haystack|) в худшем случае и меньше |haystack| в среднем.
- Грамматика языка может быть недружественной к тем или иным эвристикам, которые ускоряют поиск «в среднем».
- Архитектура процессора. Некоторые процессоры имеют автоинкрементные или SIMD-операции, которые позволяют быстро сравнить два участка ОЗУ (например,
rep cmpsd
на x86). На таких процессорах заманчиво применить алгоритм, который просто бы сравнивал needle с haystack — разумеется, не во всех позициях. - Размер алфавита. Многие алгоритмы (особенно основанные на сравнении с конца) имеют эвристики, связанные с несовпавшим символом. На больших алфавитах таблица символов будет занимать много памяти, на малых — соответствующая эвристика будет неэффективной.
- Возможность проиндексировать haystack. Если таковая есть, поиск серьёзно ускорится.
- Требуется ли одновременный поиск нескольких строк? Приблизительный поиск? Побочные свойства некоторых алгоритмов (Ахо-Корасик, двоичного алгоритма) позволяют такое.
Как правило, в текстовом редакторе достаточно взять самый простой эвристический алгоритм наподобие Бойера — Мура — Хорспула — даже очень медленный ПК справится с поиском за доли секунды. Если же объём текста измеряется гигабайтами, либо поиск запущен на сервере, который обрабатывает множество запросов — приходится выбирать наиболее удачный алгоритм из доступных. Например, программы определения плагиата осуществляют онлайн-проверку, используя алгоритмы поиска подстроки среди большого количества документов, хранящихся в собственной базе.
Алгоритмы
[править | править код]Для сокращения обозначим:
- |Σ|=σ — размер алфавита.
- |haystack|=H — длина строки, в которой ведётся поиск.
- |needle|=n — длина шаблона поиска.
Вычислительная сложность определяется до первого совпадения. Жирным шрифтом выделены важнейшие с практической точки зрения алгоритмы.
Основанные на сравнении как «чёрном ящике»
[править | править код]Во всех этих алгоритмах точка, где «иголка» не совпала со «стогом сена», не участвует в принятии решения. Это позволяет использовать стандартные функции сравнения участков памяти, зачастую оптимизированные на ассемблерном уровне под тот или иной процессор.
К этой категории относится и примитивный алгоритм поиска.
Название | Предв. обработка | Сложность | Примечания | |
---|---|---|---|---|
типичная | макс. | |||
Примитивный алгоритм | Нет | 2H | O(Hn) | |
Алгоритм Бойера — Мура — Хорспула | O(n+σ) | ~ 2H / σ[2] | O(Hn) | Упрощённый до предела алгоритм Бойера — Мура; использует только видоизменённую эвристику стоп-символа — за стоп-символ всегда берётся символ haystack, расположенный напротив последнего символа needle. |
Алгоритм быстрого поиска Алгоритм Санди |
O(n+σ) | <H | O(Hn) | Также использует исключительно эвристику стоп-символа — но за стоп-символ берётся символ haystack, идущий за последним символом needle. |
Основанные на сравнении с начала
[править | править код]Это семейство алгоритмов страдает невысокой скоростью на «хороших» данных, что компенсируется отсутствием регрессии на «плохих».
Название | Предв. обработка | Сложность | Примечания | |
---|---|---|---|---|
типичная | макс. | |||
Алгоритм Рабина-Карпа | O(n) | <H+n | O(Hn) | Хеширование позволяет серьёзно снизить сложность в среднем |
Автоматный алгоритм Алгоритм Ахо-Корасик |
O(nσ) | = H | Строит конечный автомат, который распознаёт язык, состоящий из одной-единственной строки. После небольшой модификации позволяет за один проход по haystack найти одну строку из нескольких. | |
Алгоритм Кнута-Морриса-Пратта | O(n) | ≤ 2H | Один из первых алгоритмов с линейной оценкой в худшем случае. Модификация алгоритма Ахо-Корасик, строящая автомат неявно на основе префикс-функции. | |
Алгоритм Апостолико-Крошмора | O(n) | < H | ≤1,5H | |
Алгоритм Shift-Or Bitap-алгоритм Двоичный алгоритм |
O(n+σ) | =H·ceil(n/w) | Эффективен, если размер needle (в символах) не больше размера машинного слова (в битах, обозначен как w). Легко переделывается на приблизительный поиск, поиск нескольких строк. |
Основанные на сравнении с конца
[править | править код]В этом семействе алгоритмов needle движется по haystack слева направо, но сравнение этих строк друг с другом проводится справа налево. Сравнение справа налево позволяет в случае несовпадения сдвинуть needle не на одну позицию, а на несколько.
Название | Предв. обработка | Сложность | Примечания | |
---|---|---|---|---|
типичная | макс. | |||
Алгоритм Бойера — Мура | O(n+σ) | <H | O(Hn) | Стандартный алгоритм поиска подстроки в строке. Считается наиболее эффективным алгоритмом общего назначения.[3] |
Алгоритм Чжу-Такаоки | O(n+σ²) | <H | O(Hn) | Алгоритм Бойера — Мура, оптимизированный под короткие алфавиты |
Алгоритм Апостолико-Джанкарло | O(n+σ) | <H | ≤1,5H | Одна из первых попыток получить <H в типичном случае и O(H) в худшем. Очень сложен в реализации. |
Турбо-алгоритм Бойера — Мура | O(n+σ) | <H | ≤2H | Один из наиболее эффективных алгоритмов, не дающих регрессии на «плохих» данных |
Проводящие сравнение в необычном порядке
[править | править код]Название | Предв. обработка | Сложность | Примечания | |
---|---|---|---|---|
типичная | макс. | |||
Непримитивный алгоритм | const | <H | O(Hn) | Простой алгоритм, сравнивающий второй символ, затем начиная с третьего в режиме «чёрного ящика», и, наконец, первый. При n[1]≠n[2][4] и несовпадении на второй-третьей стадии — сдвиг на 2 вправо. |
Алгоритм Райты Алгоритм Бойера — Мура — Хорспула — Райты |
O(n+σ) | <H | O(Hn) | Эмпирический алгоритм, оптимизированный под английские тексты. Сравнивает последний символ, потом первый, потом средний, потом все остальные; при несовпадении — сдвиг по Хорспулу. |
См. также
[править | править код]Примечания
[править | править код]- ↑ Brute force algorithm Архивная копия от 21 января 2009 на Wayback Machine (англ.)
- ↑ Horspool algorithm . Дата обращения: 2 мая 2013. Архивировано 29 августа 2012 года.
- ↑ Boyer-Moore algorithm . Дата обращения: 2 мая 2013. Архивировано 6 февраля 2013 года.
- ↑ Напомним, символы нумеруются с 1, как в Паскале.
Литература
[править | править код]- Гасфилд Д. Строки, деревья и последовательности в алгоритмах: Информатика и вычислительная биология = Algorithms on String, Trees, and Sequences. Computer Science and Computational Biology / Пер. с англ. И. В. Романовского. — 2-е изд. — СПб.: Невский Диалект, 2003. — 654 с. — ISBN 5-7940-0103-8, 5-94157-321-9, 0-521-58519-8.
- Смит Б. Методы и алгоритмы вычислений на строках = Computing Patterns in Strings. — М.: Вильямс, 2006. — 496 с. — ISBN 5-8459-1081-1, 0-201-39839-7.
- Окулов С. М. Алгоритмы обработки строк. — М.: Бином, 2013. — 255 с. — ISBN 978-5-9963016-2-1.
Ссылки
[править | править код]Для улучшения этой статьи желательно:
|