Алгоритм Мейна-Лоренца — различия между версиями
Mariashka (обсуждение | вклад) (Новая страница: «{{Определение |definition = '''Повтором''' (англ. ''repeatition'') называется непустая строка вида <math>\alpha...») |
Mariashka (обсуждение | вклад) |
||
Строка 30: | Строка 30: | ||
{{Утверждение | {{Утверждение | ||
|id=kindscount | |id=kindscount | ||
− | |statement=<math>2p -RS[p] \ | + | |statement=<math>2p -RS[p] \leqslant i \leqslant p - RP[p + 1]</math>, где <tex>i</tex> индекс конца повтора в строке <tex>v</tex>. |
|proof= Рассмотрим правый повтор <tex>ww</tex>.<br> | |proof= Рассмотрим правый повтор <tex>ww</tex>.<br> | ||
Обозначим как <tex>k</tex> ту часть первой полвины повтора, которая принадлежит <tex>u</tex>, а как <tex>l</tex> {{---}} ту часть первого половины, которая принадлежит <tex>v</tex>. Равные им подстроки во первой половине обозначим как <tex>m</tex> и <tex>n</tex>(см. рисунок). | Обозначим как <tex>k</tex> ту часть первой полвины повтора, которая принадлежит <tex>u</tex>, а как <tex>l</tex> {{---}} ту часть первого половины, которая принадлежит <tex>v</tex>. Равные им подстроки во первой половине обозначим как <tex>m</tex> и <tex>n</tex>(см. рисунок). | ||
Строка 40: | Строка 40: | ||
# <tex> k = u[(u.len - b + 1) .. u.len] = m = v[(i - p + 1) .. p] </tex> | # <tex> k = u[(u.len - b + 1) .. u.len] = m = v[(i - p + 1) .. p] </tex> | ||
# <tex> l = v[1 .. (i - p)] = n = v[(p + 1) .. i] </tex> | # <tex> l = v[1 .. (i - p)] = n = v[(p + 1) .. i] </tex> | ||
− | <tex>(1)</tex> эквивалентно тому, что <tex>u</tex> и <tex>v[1 .. p]</tex> имеют общий суффикс длины не менее <tex>b</tex>: <tex>2p - i = b \ | + | <tex>(1)</tex> эквивалентно тому, что <tex>u</tex> и <tex>v[1 .. p]</tex> имеют общий суффикс длины не менее <tex>b</tex>: <tex>2p - i = b \leqslant RS[p]</tex>. <br> |
− | <tex>(2)</tex> эквивалентно тому, что строки <tex> v</tex> и <tex> v[p+1..v.len]</tex> имеют общий префикс длины не менее <tex>p-b = i-p</tex>: <tex>i - p \ | + | <tex>(2)</tex> эквивалентно тому, что строки <tex> v</tex> и <tex> v[p+1..v.len]</tex> имеют общий префикс длины не менее <tex>p-b = i-p</tex>: <tex>i - p \leqslant RP[p + 1] </tex> |
}} | }} | ||
Строка 58: | Строка 58: | ||
{{Утверждение | {{Утверждение | ||
|id=kindscount | |id=kindscount | ||
− | |statement=<math> p - LS[u.len - p] \ | + | |statement=<math> p - LS[u.len - p] \leqslant i \leqslant LP[u.len - p + 1] </math> |
|proof= Рассмотрим правый повтор <tex>ww</tex>.<br> | |proof= Рассмотрим правый повтор <tex>ww</tex>.<br> | ||
Обозначим как <tex>m</tex> ту часть первой второй повтора, которая принадлежит <tex>u</tex>, а как <tex>n</tex> {{---}} ту часть второго половины, которая принадлежит <tex>v</tex>. Равные им подстроки во второй половине обозначим как <tex>k</tex> и <tex>l</tex>(см. рисунок). | Обозначим как <tex>m</tex> ту часть первой второй повтора, которая принадлежит <tex>u</tex>, а как <tex>n</tex> {{---}} ту часть второго половины, которая принадлежит <tex>v</tex>. Равные им подстроки во второй половине обозначим как <tex>k</tex> и <tex>l</tex>(см. рисунок). | ||
Строка 68: | Строка 68: | ||
# <tex> k = u[(u.len - b + 1) .. (u.len - p)] = m = u[(u.len - b + p + 1) .. u.len] </tex> | # <tex> k = u[(u.len - b + 1) .. (u.len - p)] = m = u[(u.len - b + p + 1) .. u.len] </tex> | ||
# <tex> l = u[(u.len - p + 1) .... (u.len - b + p)] = n = v[1 .... i] </tex> | # <tex> l = u[(u.len - p + 1) .... (u.len - b + p)] = n = v[1 .... i] </tex> | ||
− | <tex>(1)</tex> эквивалентно тому, что <tex>u</tex> и <tex>u[(u.len - b + 1) .. u.len]</tex> имеют общий префикс длины не менее <tex>b - p = p - i</tex>: <tex> p - i \ | + | <tex>(1)</tex> эквивалентно тому, что <tex>u</tex> и <tex>u[(u.len - b + 1) .. u.len]</tex> имеют общий префикс длины не менее <tex>b - p = p - i</tex>: <tex> p - i \leqslant LS[u.len - p]</tex>. <br> |
− | <tex>(2)</tex> эквивалентно тому, что строки <tex> v</tex> и <tex> u[(u.len - p)..u.len]</tex> имеют общий суффикс длины не менее <tex>i</tex>: <tex>i \ | + | <tex>(2)</tex> эквивалентно тому, что строки <tex> v</tex> и <tex> u[(u.len - p)..u.len]</tex> имеют общий суффикс длины не менее <tex>i</tex>: <tex>i \leqslant LP[u.len - p + 1] </tex> |
}} | }} | ||
Версия 14:47, 30 апреля 2015
Определение: |
Повтором (англ. repeatition) называется непустая строка вида |
Алгоритм Мейна-Лоренца (англ. Main-Lorentz algorithm) — алгоритм на строках, позволяющий найти все повторы в строке
заСодержание
Алгоритм
Так как повторов строке
, мы не можем хранить их в явном виде. Будем хранить повторы блоками вида , где — это длина повтора, а — промежуток индексов, в которых заканчиваются повторы такой длины. Для каждой длины может быть несколько блоков.Данный алгоритм — это алгоритм типа "разделяй и властвуй":
- Разделим строку пополам
- Заметим, что повторы делятся на две группы: пересекающие и не пересекающие границу раздела
- Рекурсивно запустимся от каждой половинки — так мы найдем повторы, которые не пересекают границу раздела
- Далее рассмотрим процесс нахождения повторов, которые пересекают границу раздела
Повторы, пересекающие границу раздела, можно разделить на две группы по положению центра повтора: правые и левые.
Нахождение правых повтров
Рассмотрим строку
, пусть — индекс начала в исходной строке- Предподсчитаем следующие массивы c помощью Z-функции:
- , то есть наибольший общий префикс строк v[i..v.len] и v
- , то есть наибольший общий суффикс строк v[1..i] и u
- Переберем длину повтора и будем искать все повторы такой длины. Для этого для каждого получим интервал индексов конца повтора в строке : (позднее покажем, как это сделать).
- Добавим к ответу, учитывая смещение в исходной строке :
Итоговая асимптотика:
Докажем следующее утверждение для нахождения интервала
:Нахождение левых повтров
Рассмотрим строку
, пусть — индекс начала в исходной строке- Предподсчитаем следующие массивы с помощью Z-функции:
- , то есть наибольший общий префикс строк u[i..u.len] и v
- , где — наибольший общий суффикс
- Переберем длину повтора и будем искать все повторы такой длины. Для этого для каждого получим интервал индексов конца повтора в строке : (позднее покажем, как это сделать).
- Добавим к ответу, учитывая смещение в исходной строке :
Итоговая асимптотика:
Докажем следующее утверждение для нахождения интервала
:Асимптотика
Ассимптотика алгоритма "разделяй и властвуй", каждый рекурсивный запуск которого линеен относительно длины строки, сортировки слиянием).
из рекурентного соотношения (аналогичное доказательство дляКоличество блоков в ответе также будет
, так как при каждом рекрсивном запуске добавляется блоков для каждой рассмотренной длины повтора, а их количество линейно относительно длины строки.Источники
- Main, M., Lorentz, R.J. — An O(n log n) Algorithm for Finding All Repetitions in a String. 1982
- Билл Смит — Методы и алгоритмы вычислений на строках. Пер. с англ.— М.:Издательский дом "Вильямс", 2006. ISBN 5-8459-1081-1