Участница:Mariashka — различия между версиями
Mariashka (обсуждение | вклад) |
Mariashka (обсуждение | вклад) |
||
Строка 10: | Строка 10: | ||
# Заметим, что повторы делятся на две группы: пересекающие и не пересекающие границу раздела | # Заметим, что повторы делятся на две группы: пересекающие и не пересекающие границу раздела | ||
# Рекурсивно запустимся от каждой половинки {{---}} так мы найдем повторы, которые не пересекают границу раздела | # Рекурсивно запустимся от каждой половинки {{---}} так мы найдем повторы, которые не пересекают границу раздела | ||
− | # | + | # Далее рассмотрим процесс нахождения повторов, которые пересекают границу раздела |
Повторы, пересекающие границу раздела, можно разделить на две группы по положению центра повтора. | Повторы, пересекающие границу раздела, можно разделить на две группы по положению центра повтора. | ||
Строка 18: | Строка 18: | ||
=== Нахождение правых повтров === | === Нахождение правых повтров === | ||
Рассмотрим строку <tex>t = uv</tex>, пусть начало <tex>t</tex> в исходной строке <tex>s</tex> {{---}} <tex>shift</tex> | Рассмотрим строку <tex>t = uv</tex>, пусть начало <tex>t</tex> в исходной строке <tex>s</tex> {{---}} <tex>shift</tex> | ||
+ | |||
+ | [[Файл:RightRepetition.png|600px]]<br> | ||
# Предподсчитаем следующие массивы: | # Предподсчитаем следующие массивы: | ||
Строка 40: | Строка 42: | ||
=== Нахождение левых повтров === | === Нахождение левых повтров === | ||
Рассмотрим строку <tex>t = uv</tex>, пусть начало <tex>t</tex> в исходной строке <tex>s</tex> {{---}} <tex>shift</tex> | Рассмотрим строку <tex>t = uv</tex>, пусть начало <tex>t</tex> в исходной строке <tex>s</tex> {{---}} <tex>shift</tex> | ||
+ | |||
+ | [[Файл:LeftRepetition.png|600px]]<br> | ||
# Предподсчитаем следующие массивы: | # Предподсчитаем следующие массивы: |
Версия 19:12, 27 апреля 2015
Определение: |
Повтором (англ. repeatition) называется непустая строка вида |
Алгоритм Мейна-Лоренца (англ. Main-Lorentz algorithm) — алгоритм на строках, позволяющий найти все повторы в строке
заАлгоритм
Данный алгоритм — это алгоритм "разделяй и властвуй":
- Разделим строку пополам
- Заметим, что повторы делятся на две группы: пересекающие и не пересекающие границу раздела
- Рекурсивно запустимся от каждой половинки — так мы найдем повторы, которые не пересекают границу раздела
- Далее рассмотрим процесс нахождения повторов, которые пересекают границу раздела
Повторы, пересекающие границу раздела, можно разделить на две группы по положению центра повтора.
Так как повторов строке
, мы не можем хранить их в явном виде. Будем хранить повторы блоками вида , где — это длина повтора, а — промежуток индексов, в которых заканчиваются повторы такой длины.Нахождение правых повтров
Рассмотрим строку
, пусть начало в исходной строке —- Предподсчитаем следующие массивы:
- , где — наибольший общий префикс
- , где — наибольший общий суффикс
- Переберем длину повтора . Для каждого получим интервал индексов конца повтора в строке : .
- Добавим к ответу, учитывая смещение в исходной строке :
Итоговая асимптотика:
Докажем следующее утверждение для нахождения интервала
:Утверждение: |
Пусть i - индекс конца повтора в строке v, тогда b = 2p - i - длина части повтора принадлежащей u. Пусть наш повтор TODO , тогда |
Нахождение левых повтров
Рассмотрим строку
, пусть начало в исходной строке —- Предподсчитаем следующие массивы:
- , где — наибольший общий префикс
- , где — наибольший общий суффикс
- Переберем длину повтора . Для каждого получим интервал индексов конца повтора в строке : .
- Добавим к ответу, учитывая смещение в исходной строке :
Итоговая асимптотика:
Докажем следующее утверждение для нахождения интервала
:Утверждение: |
TODO |
Асимптотика
Ассимптотика алгоритма "разделяй и властвуй", каждый рекурсивный запуск которого линеен относительно длины строки,
.Количество блоков в ответе также будет
, так как при каждом рекрсивном запуске добавляется блоков для каждой рассмотренной длины повтора, а их количество линейно относительно длины строки.