Участница:Mariashka — различия между версиями
Mariashka (обсуждение | вклад) |
Mariashka (обсуждение | вклад) |
||
| Строка 6: | Строка 6: | ||
== Алгоритм == | == Алгоритм == | ||
| − | Данный алгоритм {{---}} это алгоритм "разделяй и властвуй": | + | Так как повторов строке <tex> \Omega(n^2)</tex>, мы не можем хранить их в явном виде. Будем хранить повторы блоками вида <tex>(length, first, last)</tex>, где <tex> length </tex> {{---}} это длина повтора, а <tex> [first, last] </tex> {{---}} промежуток индексов, в которых заканчиваются повторы такой длины. |
| + | |||
| + | Данный алгоритм {{---}} это алгоритм типа "разделяй и властвуй": | ||
# Разделим строку пополам | # Разделим строку пополам | ||
# Заметим, что повторы делятся на две группы: пересекающие и не пересекающие границу раздела | # Заметим, что повторы делятся на две группы: пересекающие и не пересекающие границу раздела | ||
| Строка 12: | Строка 14: | ||
# Далее рассмотрим процесс нахождения повторов, которые пересекают границу раздела | # Далее рассмотрим процесс нахождения повторов, которые пересекают границу раздела | ||
| − | Повторы, пересекающие границу раздела, можно разделить на две группы по положению центра повтора | + | Повторы, пересекающие границу раздела, можно разделить на две группы по положению центра повтора: правые и левые. |
| − | |||
| − | |||
=== Нахождение правых повтров === | === Нахождение правых повтров === | ||
Версия 20:57, 28 апреля 2015
| Определение: |
| Повтором (англ. repeatition) называется непустая строка вида |
Алгоритм Мейна-Лоренца (англ. Main-Lorentz algorithm) — алгоритм на строках, позволяющий найти все повторы в строке за
Алгоритм
Так как повторов строке , мы не можем хранить их в явном виде. Будем хранить повторы блоками вида , где — это длина повтора, а — промежуток индексов, в которых заканчиваются повторы такой длины.
Данный алгоритм — это алгоритм типа "разделяй и властвуй":
- Разделим строку пополам
- Заметим, что повторы делятся на две группы: пересекающие и не пересекающие границу раздела
- Рекурсивно запустимся от каждой половинки — так мы найдем повторы, которые не пересекают границу раздела
- Далее рассмотрим процесс нахождения повторов, которые пересекают границу раздела
Повторы, пересекающие границу раздела, можно разделить на две группы по положению центра повтора: правые и левые.
Нахождение правых повтров
Рассмотрим строку , пусть начало в исходной строке —
- Предподсчитаем следующие массивы c помощью z-функции:
- , где — наибольший общий префикс
- , где — наибольший общий суффикс
- Переберем длину повтора . Для каждого получим интервал индексов конца повтора в строке : .
- Добавим к ответу, учитывая смещение в исходной строке :
Итоговая асимптотика:
Докажем следующее утверждение для нахождения интервала :
| Утверждение: |
, где индекс конца повтора в строке . |
|
Рассмотрим правый повтор .
Пусть — длина , то есть той части повтора, которая принадлежит .
Заметим, что и . эквивалентно тому, что и имеют общий суффикс длины не менее : . |
Нахождение левых повтров
Рассмотрим строку , пусть начало в исходной строке —
- Предподсчитаем следующие массивы с помощью z-функции:
- , где — наибольший общий префикс
- , где — наибольший общий суффикс
- Переберем длину повтора . Для каждого получим интервал индексов конца повтора в строке : .
- Добавим к ответу, учитывая смещение в исходной строке :
Итоговая асимптотика:
Докажем следующее утверждение для нахождения интервала :
| Утверждение: |
|
Пусть — длина , то есть той части повтора, которая принадлежит .
Заметим, что и . эквивалентно тому, что и имеют общий префикс длины не менее : . |
Асимптотика
Ассимптотика алгоритма "разделяй и властвуй", каждый рекурсивный запуск которого линеен относительно длины строки, .
Количество блоков в ответе также будет , так как при каждом рекрсивном запуске добавляется блоков для каждой рассмотренной длины повтора, а их количество линейно относительно длины строки.