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

Материал из Викиконспекты
Перейти к: навигация, поиск

Поиск подстроки в строке (англ. String searching algorithm) — класс алгоритмов над строками, которые позволяют найти паттерн (pattern) в тексте (text).

Классификация алгоритмов поиска подстроки в строке[править]

Сравнение — «чёрный ящик»[править]

Во всех алгоритмах этого типа сравнение является «чёрным ящиком» для программиста.

Преимущества:

  • позволяет использовать стандартные функции сравнения участков памяти (man *cmp(3)), которые, зачастую, оптимизированы под конкретное железо.

Недостатки:

  • не выдается точка, в которой произошло несовпадение.

По порядку сравнения паттерна в тексте[править]

Прямой[править]

Преимущества:

  • отсутствие регрессии на «плохих» данных.

Недостатки:

  • не самая хорошая средняя асимптотическая сложность.

Обратный[править]

Паттерн движется по тексту слева направо, но сравнение подстрок происходит справа налево.

Преимущества:

  • при несовпадении позволяет перемещать паттерн по строке сразу на несколько символов.

Недостатки:

  • производительность сильно зависит от данных.

Сравнение в необычном порядке[править]

Специфические алгоритмы, основанные, как правило, на некоторых эмпирических наблюдениях над словарём.[1]

По количеству поисковых шаблонов[править]

Сколько поисковых шаблонов может обработать алгоритм за один раз.

  • один шаблон (англ. single pattern algorithms)
  • конечное количество шаблонов (англ. finite set of patterns)
  • бесконечное количество шаблонов (англ. infinite number of patterns) (см. Теория формальных языков)

По необходимости препроцессинга текста[править]

Виды препроцессинга:

Алгоритмы, использующие препроцессинг — одни из самых быстрых в этом классе.

Сравнение алгоритмов[править]

  • [math]|\Sigma| = \sigma[/math]­ — размер алфавита
  • [math]|text| = t[/math] — длина текста
  • [math]|pattern| = p[/math] — длина паттерна
  • [math]a[/math] — размер ответа(кол-во пар)
  • [math]m[/math] — суммарная длина всех паттернов
Название Среднее Худшее Препроцессинг Дополнительная память Кол-во поисковых шаблонов Порядок сравнения Описание
Наивный алгоритм
(Brute Force algorithm)
[math]O(p \cdot (t - p))[/math] [math]O(t^2)[/math] [math]O(1)[/math] Single Прямой Сравнение — «чёрный ящик». Если [math]p[/math] достаточно мало по сравнению с [math]t[/math], то асимптотика будет близкой к [math]O(t)[/math], что позволяет использовать его на практике в случаях, когда паттерн много меньше текста (например, Ctrl+F в браузерах)
Поиск подстроки в строке с помощью Z-функции [math]O(t)[/math] [math]O(t)[/math] [math]O(p + t)[/math] [math]O(p)[/math] Single Прямой
Алгоритм Рабина-Карпа
(Karp-Rabin algorithm)
[math]O(p + t)[/math] [math]O(pt)[/math] [math]O(p)[/math] [math]O(1)[/math] Single / Finite Прямой Данный алгоритм использует хэширование, что снижает скорость в среднем. Можно модифицировать для поиска нескольких паттернов
Алгоритм Кнута-Морриса-Пратта
(Knuth-Morris-Pratt algorith)
[math]O(p + t)[/math] [math]O(p + t)[/math] [math]O(p)[/math] [math]O(p)[/math] Single Прямой Использует префикс-функцию
Алгоритм Колусси
(Colussi algorithm)
[math]O(t)[/math] [math]O(t)[/math] [math]O(p)[/math] [math]O(p)[/math] Single Прямой / Обратный Оптимизация Алгоритма Кнута-Морриса-Пратта использует как прямой, так и обратный обход
Алгоритм Ахо-Корасик
(Aho–Corasick string matching algorithm)
[math]O(m + t + a)[/math] [math]O(t)[/math]
[math]O(m)[/math]
[math]O(m\sigma)[/math] Finite Прямой Строит конечный автомат. Можно хранить таблицу переходов как индексный массив (array), а можно как Красно-черное дерево. В последнем случае уменьшится расход памяти, но ухудшится асимптотика
Алгоритм Shift-Or [math]O(t)[/math] [math]O(t \cdot \dfrac{n}{w})[/math]
[math]w[/math] — размер машинного слова
[math]O(p + \sigma)[/math] [math]O(p + \sigma)[/math] Single Прямой Использует тот факт, что в современных процессорах битовые сдвиг и или являются атомарными. Эффективен, если [math]p \leqslant w[/math]. Иначе деградирует и по памяти, и по сложности
Алгоритм Бойера-Мура
(Boyer-Moore algorithm)
[math]O(t)[/math] [math]O(pt)[/math] [math]O(p + \sigma)[/math] [math]O(p + \sigma)[/math] Single Обратный Считается наиболее быстрым из алгоритмов общего назначения. Использует эвристики. Существует большое количество оптимизаций[2]
Поиск подстроки в строке с помощью суффиксного массива
(Suffix array)
[math]O(p\log t)[/math] [math]O(p\log t)[/math] [math]O(t)[/math] [math]O(t)[/math] Single Прямой Использует Суффиксный массив. Если использовать Largest common prefix (lcp), то можно уменьшить асимптотику до [math]O(p + \log t)[/math]. Суффиксный массив можно строить стандартными способами или алгоритмом Карккайнена-Сандерса. Асимптотика приведена для построения суффиксного массива с помощью алгоритма Карккайнена-Сандерса
Поиск подстроки в строке с помощью суффиксного дерева
(Suffix tree)
[math]O(p)[/math] [math]O(p)[/math] [math]O(t)[/math] [math]O(t)[/math] Single Прямой Позволяет выполнять поиск подстроки в строке за линейное время
Алгоритм Апостолико-Крочемора
( Apostolico-Crochemore algorithm)
[math]O(t)[/math] [math]O(t)[/math] [math]O(p)[/math] [math]O(p)[/math] Single Прямой В худшем случае выполнит [math]\dfrac{3}{2} n[/math] сравнений.

Примечания[править]

Источники информации[править]