Участница:Mariashka — различия между версиями
Mariashka (обсуждение | вклад) |
Mariashka (обсуждение | вклад) |
||
Строка 21: | Строка 21: | ||
[[Файл:RightRepetition.png|600px]]<br> | [[Файл:RightRepetition.png|600px]]<br> | ||
− | # Предподсчитаем следующие массивы: | + | # Предподсчитаем следующие массивы c помощью z-функции: |
## <tex> RP[i] = lcp(v[i..v.len], v) </tex>, где <tex> lcp </tex> {{---}} наибольший общий префикс | ## <tex> RP[i] = lcp(v[i..v.len], v) </tex>, где <tex> lcp </tex> {{---}} наибольший общий префикс | ||
## <tex> RS[i] = lcs(v[1..i], u) </tex>, где <tex> lcs </tex> {{---}} наибольший общий суффикс | ## <tex> RS[i] = lcs(v[1..i], u) </tex>, где <tex> lcs </tex> {{---}} наибольший общий суффикс | ||
Строка 32: | Строка 32: | ||
{{Утверждение | {{Утверждение | ||
|id=kindscount | |id=kindscount | ||
− | |statement=<math>2p -RS[p] \leq i \leq p - RP[p + 1]</math> | + | |statement=<math>2p -RS[p] \leq i \leq p - RP[p + 1]</math>, где <tex>i</tex> индекс конца повтора в строке <tex>v</tex>. |
− | + | |proof= Рассмотрим правый повтор <tex>ww</tex>. | |
− | + | Пусть <tex> b </tex> {{---}} длина <tex>k</tex>, то есть той части повтора, которая принадлежит <tex>u</tex>. | |
− | < | + | Заметим, что <tex>w = k + l = m + n</tex> и <tex> k = m, l = n </tex>. <br> |
− | + | Тогда | |
− | + | # <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>(1)</tex> эквивалентно тому, что <tex>u</tex> и <tex>v[1 .. p]</tex> имеют общий суффикс длины не менее <tex>b</tex>: <tex>2p - i = b \leq 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 \leq RP[p + 1] </tex> | ||
}} | }} | ||
Строка 45: | Строка 48: | ||
[[Файл:LeftRepetition.png|600px]]<br> | [[Файл:LeftRepetition.png|600px]]<br> | ||
− | # Предподсчитаем следующие массивы: | + | # Предподсчитаем следующие массивы с помощью z-функции: |
## <tex> LP[i] = lcp(u[i..u.len], u) </tex>, где <tex> lcp </tex> {{---}} наибольший общий префикс | ## <tex> LP[i] = lcp(u[i..u.len], u) </tex>, где <tex> lcp </tex> {{---}} наибольший общий префикс | ||
## <tex> LS[i] = lcs(u[1..i], u) </tex>, где <tex> lcs </tex> {{---}} наибольший общий суффикс | ## <tex> LS[i] = lcs(u[1..i], u) </tex>, где <tex> lcs </tex> {{---}} наибольший общий суффикс | ||
Строка 57: | Строка 60: | ||
|id=kindscount | |id=kindscount | ||
|statement=<math> p - LS[u.len - p] \leq i \leq LP[u.len - p + 1] </math> | |statement=<math> p - LS[u.len - p] \leq i \leq LP[u.len - p + 1] </math> | ||
− | |proof= | + | |proof= Пусть <tex> b </tex> {{---}} длина <tex>k+l+m</tex>, то есть той части повтора, которая принадлежит <tex>u</tex>. |
+ | Заметим, что <tex>w = k + l = m + n</tex> и <tex> k = m, l = n </tex>. <br> | ||
+ | Тогда | ||
+ | # <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>(1)</tex> эквивалентно тому, что <tex>u</tex> и <tex>u[(u.len - b + 1) .. u.len]</tex> имеют общий префикс длины не менее <tex>b - p = p - i</tex>: <tex> p - i \leq 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 \leq LP[u.len - p + 1] </tex> | ||
}} | }} | ||
Версия 20:02, 27 апреля 2015
Определение: |
Повтором (англ. repeatition) называется непустая строка вида |
Алгоритм Мейна-Лоренца (англ. Main-Lorentz algorithm) — алгоритм на строках, позволяющий найти все повторы в строке
заАлгоритм
Данный алгоритм — это алгоритм "разделяй и властвуй":
- Разделим строку пополам
- Заметим, что повторы делятся на две группы: пересекающие и не пересекающие границу раздела
- Рекурсивно запустимся от каждой половинки — так мы найдем повторы, которые не пересекают границу раздела
- Далее рассмотрим процесс нахождения повторов, которые пересекают границу раздела
Повторы, пересекающие границу раздела, можно разделить на две группы по положению центра повтора.
Так как повторов строке
, мы не можем хранить их в явном виде. Будем хранить повторы блоками вида , где — это длина повтора, а — промежуток индексов, в которых заканчиваются повторы такой длины.Нахождение правых повтров
Рассмотрим строку
, пусть начало в исходной строке —- Предподсчитаем следующие массивы c помощью z-функции:
- , где — наибольший общий префикс
- , где — наибольший общий суффикс
- Переберем длину повтора . Для каждого получим интервал индексов конца повтора в строке : .
- Добавим к ответу, учитывая смещение в исходной строке :
Итоговая асимптотика:
Докажем следующее утверждение для нахождения интервала
:Утверждение: |
, где индекс конца повтора в строке . |
Рассмотрим правый повтор
|
Нахождение левых повтров
Рассмотрим строку
, пусть начало в исходной строке —- Предподсчитаем следующие массивы с помощью z-функции:
- , где — наибольший общий префикс
- , где — наибольший общий суффикс
- Переберем длину повтора . Для каждого получим интервал индексов конца повтора в строке : .
- Добавим к ответу, учитывая смещение в исходной строке :
Итоговая асимптотика:
Докажем следующее утверждение для нахождения интервала
:Утверждение: |
Пусть
|
Асимптотика
Ассимптотика алгоритма "разделяй и властвуй", каждый рекурсивный запуск которого линеен относительно длины строки,
.Количество блоков в ответе также будет
, так как при каждом рекрсивном запуске добавляется блоков для каждой рассмотренной длины повтора, а их количество линейно относительно длины строки.