Участница: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= Пусть i - индекс конца повтора в строке v, тогда b = 2p - i - длина части повтора принадлежащей u.
+
|proof= Рассмотрим правый повтор <tex>ww</tex>.
Пусть наш повтор <math>\alpha\alpha</math>, тогда
+
Пусть <tex> b </tex> {{---}} длина <tex>k</tex>, то есть той части повтора, которая принадлежит <tex>u</tex>.
<math>\alpha = u[(u.len - b + 1) .. (u.len)] + v[1 .. (i - p)] = v[(i - p + 1) .. i] </math>
+
Заметим, что <tex>w = k + l = m + n</tex> и <tex> k = m, l = n </tex>. <br>
 
+
Тогда
TODO
+
# <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= TODO
+
|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) называется непустая строка вида [math]\alpha\alpha[/math]

Алгоритм Мейна-Лоренца (англ. Main-Lorentz algorithm) — алгоритм на строках, позволяющий найти все повторы в строке [math]s[1..n][/math] за [math]O(n \log n)[/math]

Алгоритм

Данный алгоритм — это алгоритм "разделяй и властвуй":

  1. Разделим строку пополам
  2. Заметим, что повторы делятся на две группы: пересекающие и не пересекающие границу раздела
  3. Рекурсивно запустимся от каждой половинки — так мы найдем повторы, которые не пересекают границу раздела
  4. Далее рассмотрим процесс нахождения повторов, которые пересекают границу раздела

Повторы, пересекающие границу раздела, можно разделить на две группы по положению центра повтора.

Так как повторов строке [math] \Omega(n^2)[/math], мы не можем хранить их в явном виде. Будем хранить повторы блоками вида [math](length, first, last)[/math], где [math] length [/math] — это длина повтора, а [math] [first, last] [/math] — промежуток индексов, в которых заканчиваются повторы такой длины.

Нахождение правых повтров

Рассмотрим строку [math]t = uv[/math], пусть начало [math]t[/math] в исходной строке [math]s[/math][math]shift[/math]

RightRepetition.png

  1. Предподсчитаем следующие массивы c помощью z-функции:
    1. [math] RP[i] = lcp(v[i..v.len], v) [/math], где [math] lcp [/math] — наибольший общий префикс
    2. [math] RS[i] = lcs(v[1..i], u) [/math], где [math] lcs [/math] — наибольший общий суффикс
  2. Переберем длину повтора [math] 2p [/math]. Для каждого [math] p [/math] получим интервал индексов конца повтора в строке [math] v [/math]: [math] [x, y] [/math].
  3. Добавим к ответу, учитывая смещение в исходной строке [math] s [/math] : [math](2p, x + shift + u.len, y + shift + u.len) [/math]

Итоговая асимптотика: [math] O(t) [/math]

Докажем следующее утверждение для нахождения интервала [math] [x, y] [/math]:

Утверждение:
[math]2p -RS[p] \leq i \leq p - RP[p + 1][/math], где [math]i[/math] индекс конца повтора в строке [math]v[/math].
[math]\triangleright[/math]

Рассмотрим правый повтор [math]ww[/math]. Пусть [math] b [/math] — длина [math]k[/math], то есть той части повтора, которая принадлежит [math]u[/math]. Заметим, что [math]w = k + l = m + n[/math] и [math] k = m, l = n [/math].
Тогда

  1. [math] k = u[(u.len - b + 1) .. u.len] = m = v[(i - p + 1) .. p] [/math]
  2. [math] l = v[1 .. (i - p)] = n = v[(p + 1) .. i] [/math]

[math](1)[/math] эквивалентно тому, что [math]u[/math] и [math]v[1 .. p][/math] имеют общий суффикс длины не менее [math]b[/math]: [math]2p - i = b \leq RS[p][/math].

[math](2)[/math] эквивалентно тому, что строки [math] v[/math] и [math] v[p+1..v.len][/math] имеют общий префикс длины не менее [math]p-b = i-p[/math]: [math]i - p \leq RP[p + 1] [/math]
[math]\triangleleft[/math]

Нахождение левых повтров

Рассмотрим строку [math]t = uv[/math], пусть начало [math]t[/math] в исходной строке [math]s[/math][math]shift[/math]

LeftRepetition.png

  1. Предподсчитаем следующие массивы с помощью z-функции:
    1. [math] LP[i] = lcp(u[i..u.len], u) [/math], где [math] lcp [/math] — наибольший общий префикс
    2. [math] LS[i] = lcs(u[1..i], u) [/math], где [math] lcs [/math] — наибольший общий суффикс
  2. Переберем длину повтора [math] 2p [/math]. Для каждого [math] p [/math] получим интервал индексов конца повтора в строке [math] v [/math]: [math] [x, y] [/math].
  3. Добавим к ответу, учитывая смещение в исходной строке [math] s [/math] : [math](2p, x + shift + u.len, y + shift + u.len) [/math]

Итоговая асимптотика: [math] O(t) [/math]

Докажем следующее утверждение для нахождения интервала [math] [x, y] [/math]:

Утверждение:
[math] p - LS[u.len - p] \leq i \leq LP[u.len - p + 1] [/math]
[math]\triangleright[/math]

Пусть [math] b [/math] — длина [math]k+l+m[/math], то есть той части повтора, которая принадлежит [math]u[/math]. Заметим, что [math]w = k + l = m + n[/math] и [math] k = m, l = n [/math].
Тогда

  1. [math] k = u[(u.len - b + 1) .. (u.len - p)] = m = u[(u.len - b + p + 1) .. u.len] [/math]
  2. [math] l = u[(u.len - p + 1) .... (u.len - b + p)] = n = v[1 .... i] [/math]

[math](1)[/math] эквивалентно тому, что [math]u[/math] и [math]u[(u.len - b + 1) .. u.len][/math] имеют общий префикс длины не менее [math]b - p = p - i[/math]: [math] p - i \leq LS[u.len - p][/math].

[math](2)[/math] эквивалентно тому, что строки [math] v[/math] и [math] u[(u.len - p)..u.len][/math] имеют общий суффикс длины не менее [math]i[/math]: [math]i \leq LP[u.len - p + 1] [/math]
[math]\triangleleft[/math]

Асимптотика

Ассимптотика алгоритма "разделяй и властвуй", каждый рекурсивный запуск которого линеен относительно длины строки, [math] O(n \log n) [/math].

Количество блоков в ответе также будет [math] O(n \log n) [/math], так как при каждом рекрсивном запуске добавляется [math] O(1) [/math] блоков для каждой рассмотренной длины повтора, а их количество линейно относительно длины строки.