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