Поиск подстроки в строке с использованием хеширования. Алгоритм Рабина-Карпа — различия между версиями
(→Алгоритм) |
|||
| Строка 27: | Строка 27: | ||
'''2:''' hp := hash(p[1..m]) | '''2:''' hp := hash(p[1..m]) | ||
'''3:''' h := hash(s[1..m]) | '''3:''' h := hash(s[1..m]) | ||
| − | '''4:''' for i from 1 to (n-m+1) | + | '''4:''' for i from 1 to (n - m + 1) |
'''5:''' if h = hp | '''5:''' if h = hp | ||
| − | '''6:''' add i | + | '''6:''' answer.add(i) |
'''7:''' h := p <tex>\cdot</tex> h - <tex>p^{m}</tex>s[i] + s[i + m] | '''7:''' h := p <tex>\cdot</tex> h - <tex>p^{m}</tex>s[i] + s[i + m] | ||
| − | '''8:''' return not found | + | '''8:''' if ans.size = 0 |
| + | '''9:''' return not found | ||
| + | '''10:''' else | ||
| + | '''11:''' return answer | ||
7 строка была получена с помощью быстрого пересчёта хеша. Мы считаем, что <tex>s[n + 1]</tex> - пустой символ. | 7 строка была получена с помощью быстрого пересчёта хеша. Мы считаем, что <tex>s[n + 1]</tex> - пустой символ. | ||
Версия 21:45, 24 марта 2012
Алгоритм Рабина — Карпа — это алгоритм поиска подстроки в строке, используя хеширование.
Метод хеширования
Выберем полиномиальный хеш - mod , где - это некоторое простое число, а - некоторое большое число, чтобы было меньше коллизий (обычно берётся или , чтобы модуль брался автоматически - при переполнении типов;). Заметим, что если 2 строчки имеют одинаковый хэш, то они в большинстве таких случаев равны.
Давайте научимся при удалении первого символа строки и добавлении символа в конец считать хеш новой строки при помощи хеша изначальной строки за :
.
.
Получается : .
Алгоритм
У нас есть шаблон - . У нас есть строка - . Мы хотим найти все вхождения шаблона в строку.
Давайте посчитаем и .
И для считаем - сравниваем с . Если они получаются равными - то мы считаем, что подстрока входит в строку (начиная с позиции ;) или мы проверяем, что подстрока является шаблоном, для этого выберем случайные символы из строк и сравним их.
Следует предподсчитать .
Псевдо-код:
1: function RabinKarp(string s[1..n], string p[1..m]) 2: hp := hash(p[1..m]) 3: h := hash(s[1..m]) 4: for i from 1 to (n - m + 1) 5: if h = hp 6: answer.add(i) 7: h := p h - s[i] + s[i + m] 8: if ans.size = 0 9: return not found 10: else 11: return answer
7 строка была получена с помощью быстрого пересчёта хеша. Мы считаем, что - пустой символ.
Посчитаем время работы.
Изначальный подсчёт хешей - . В цикле всего итераций - каждая выполняется за . Итого - .
Литература
Кормен Т., Лейзерсон Ч., Ривест Р. Алгоритмы: построение и анализ. — 2-е изд. — М.: Издательский дом «Вильямс», 2007. — С. 1296.