Поиск подстроки в строке с использованием хеширования. Алгоритм Рабина-Карпа — различия между версиями
(→Метод хеширования) |
|||
| Строка 44: | Строка 44: | ||
Например если взять <tex> r = 2^{32}, p = 237 </tex>, за <tex> s </tex> принять [[Слово_Туэ-Морса | строку Туэ-Морса]]<ref>[http://codeforces.ru/blog/entry/4898 Codeforces: Anti-hash test]</ref> длиной <tex> 1024 </tex> , то алгоритм находит лишние вхождения почти в половине случаев. | Например если взять <tex> r = 2^{32}, p = 237 </tex>, за <tex> s </tex> принять [[Слово_Туэ-Морса | строку Туэ-Морса]]<ref>[http://codeforces.ru/blog/entry/4898 Codeforces: Anti-hash test]</ref> длиной <tex> 1024 </tex> , то алгоритм находит лишние вхождения почти в половине случаев. | ||
| + | |||
| + | == См. также == | ||
| + | *[[Наивный алгоритм поиска подстроки в строке]] | ||
| + | *[[Поиск наибольшей общей подстроки двух строк с использованием хеширования]] | ||
== Примечания == | == Примечания == | ||
| Строка 51: | Строка 55: | ||
== Источники информации == | == Источники информации == | ||
* ''Кормен, Томас Х., Лейзерсон, Чарльз И., Ривест, Рональд Л., Штайн Клиффорд'' '''Алгоритмы: построение и анализ''', 3-е издание. Пер. с англ. — М.:Издательский дом "Вильямс", 2014. — 1328 с.: ил. — ISBN 978-5-8459-1794-2 (рус.) — страницы 1036–1041. | * ''Кормен, Томас Х., Лейзерсон, Чарльз И., Ривест, Рональд Л., Штайн Клиффорд'' '''Алгоритмы: построение и анализ''', 3-е издание. Пер. с англ. — М.:Издательский дом "Вильямс", 2014. — 1328 с.: ил. — ISBN 978-5-8459-1794-2 (рус.) — страницы 1036–1041. | ||
| − | |||
| − | |||
| − | |||
*[http://codeforces.ru/blog/entry/4898 Codeforces: Anti-hash test] | *[http://codeforces.ru/blog/entry/4898 Codeforces: Anti-hash test] | ||
Версия 23:28, 14 июня 2015
Алгоритм Рабина-Карпа предназначен для поиска подстроки в строке.
Содержание
Метод хеширования
Для решения задачи удобно использовать полиномиальный хеш, так его легко пересчитывать: , где — это некоторое простое число, а — некоторое большое число, для уменьшения числа коллизий (обычно берётся или , чтобы модуль брался автоматически при переполнении типов). Стоит обратить внимание, что если 2 строчки имеют одинаковый хеш, то они в большинстве таких случаев равны.
При удалении первого символа строки и добавлении символа в конец считать хеш новой строки при помощи хеша изначальной строки возможно за :
.
.
Получается : .
Алгоритм
Алгоритм начинается с подсчета и .
Для вычисляется и сравнивается с . Если они оказались равны, то образец скорее всего содержится в строке начиная с позиции , хотя возможны и ложные срабатывания алгоритма. Если требуется свести такие срабатывания к минимуму или исключить вовсе, то применяют сравнение некоторых символов из этих строк, которые выбраны случайным образом, или применяют явное сравнение строк, как в наивном алгоритме поиска подстроки в строке. В первом случае проверка произойдет быстрее, но вероятность ложного срабатывания, хоть и небольшая, останется. Во втором случае проверка займет время, равное длине образца, но полностью исключит возможность ложного срабатывания.
Для ускорения работы алгоритма оптимально предпосчитать .
Псевдокод
Приведем пример псевдокода, который находит все вхождения строки в и возвращает массив позиций, откуда начинаются вхождения.
vector<int> rabinKarp (s : string, w : string):
vector<int> answer
int n = s.length
int m = w.length
int hashS = hash(s[1..m])
int hashW = hash(w[1..m])
for i = 1 to n - m + 1
if hashS == hashW
answer.add(i)
hashS = (p * hashS - p * hash(s[i]) + hash(s[i + m])) mod r //r - некоторое большое число, p - некоторое просто число
return answer
Новый хеш был получен с помощью быстрого пересчёта. Для сохранения корректности алгоритма нужно считать, что — пустой символ.
Время работы
Изначальный подсчёт хешей выполняется за . В цикле всего итераций, каждая выполняется за . Итоговое время работы алгоритма .
Надёжность
Если количество подстрок данной строки превышает количество хешей, то наступление коллизий неизбежно. Но даже при относительно небольших строках вероятность коллизий может быть высока, не говоря уже о способах составления специальных строк, где алгоритм на хешах выдаёт частые ложные срабатывания.
Например если взять , за принять строку Туэ-Морса[1] длиной , то алгоритм находит лишние вхождения почти в половине случаев.
См. также
- Наивный алгоритм поиска подстроки в строке
- Поиск наибольшей общей подстроки двух строк с использованием хеширования
Примечания
Источники информации
- Кормен, Томас Х., Лейзерсон, Чарльз И., Ривест, Рональд Л., Штайн Клиффорд Алгоритмы: построение и анализ, 3-е издание. Пер. с англ. — М.:Издательский дом "Вильямс", 2014. — 1328 с.: ил. — ISBN 978-5-8459-1794-2 (рус.) — страницы 1036–1041.
- Codeforces: Anti-hash test