1679
правок
Изменения
→Алгоритм skew
# Восстановив массив <tex> A_{S_o} </tex>, получаем [7, 3, 5, 1], что действительно является суффиксным массивом для нечетных суффиксов.
== Алгоритм skew Каркайнена-Сандерса ==
Изменим изначальный алгоритм следующим образом:
# Построим суффиксный массив для суффиксов, соответствующих не кратным трем позициям. Рекурсивно сведем это к построению суффиксного массива для строки длиной в две трети исходной.
<tex>A_{S_0}</tex> = []
M = []
for i = 0..2n/3- 1:
if <tex> A_{S_{12}}</tex>[i] % 3 == 1:
M.add(Pair(S[A_{S_{12}}</tex>[i] - 1], A_{S_{12}}</tex>[i]))
stable_sort(M)
for i = 0..n/3- 1:
<tex>A_{S_0}</tex>.add(M[i].second - 1)
Аналогично, второй шаг требует <tex> O(n) </tex> времени.
=== Шаг 3 ===
На этом шаге мы должны слить суффиксные массивы <tex> A_{S_0} </tex> и <tex> A_{S_{12}} </tex>, чтобы получить суффиксный массив <tex> A_{S} </tex> для всей строки <tex> S </tex>.
Применим стандартный алгоритм слияния двух отсортированных массивов. Заметим, что явно массивы не отсортированы, но сотвествующие элементам массива суффиксы — отсортированы.
Пусть на какой-то итерации слияния мы сравниваем суффиксы, соответствующие позициям <tex> i </tex>, равной 1 по модулю 3, и <tex> j </tex> (она всегда будет равна 0 по модулю 3). Это аналогично сравнению пар <tex> (S[i], S[i+1..n-1]) </tex> и <tex> (S[j], S[j+1..n-1]) </tex>. Сравнить первые элементы пар мы можем за <tex> O(1) </tex>, а относительный порядок вторых элементов пар нам уже известен, так как они соотвествуют позициям, равным 2 и 1 по модулю 3 соответственно.
Аналогично, пусть на какой-то итерации слияния мы сравниваем суффиксы, соответствующие позициям <tex> i </tex>, равной 2 по модулю 3, и <tex> j </tex> (она всегда будет равна 0 по модулю 3). Тогда это аналогично сравнению троек <tex> (S[i], S[i+1], S[i+2..n-1]) </tex> и <tex> (S[j], S[j+1], S[j+2..n-1]) </tex>, что аналогично можно делать за <tex> O(1) </tex>.
Псевдокод этой фазы:
<tex>A_{S}</tex> = []
// Вначале предподсчитаем за O(n) обратные перестановки для суффиксных массивов, то есть массивы Order такие, что A[Order[i]] = i.
// Тогда мы сможем за O(1) сравнивать суффиксы по их позиции.
Order12 = inverse(<tex>A_{S_{12}}</tex>)
Order0 = inverse(<tex>A_{S_0}</tex>)
while i < 2 * n / 3 and j < n / 3:
pos12 = <tex> A_{S_{12}} </tex>[i]
pos0 = <tex> A_{0} </tex>[j]
if pos12 % 3 == 1:
if Pair(S[pos12], Order12[pos12 + 1]) < Pair(S[pos0], Order0[pos0 + 1]):
<tex>A_{S}</tex>.add(pos12)
i++
else:
<tex>A_{S}</tex>.add(pos0)
j++
else:
if Triple(S[pos12], S[pos12 + 1], Order12[pos12 + 2]) < Triple(S[pos0], S[pos0 + 1], Order0[pos0 + 2]):
<tex>A_{S}</tex>.add(pos12)
i++
else:
<tex>A_{S}</tex>.add(pos0)
j++
while i < 2 * n / 3:
<tex>A_{S}</tex>.add(<tex> A_{S_{12}} </tex>[i])
i++
while j < n / 3:
<tex>A_{S}</tex>.add(<tex> A_{S_{0}} </tex>[j])
i++
Таким образом, получили простой метод сливания за <tex> O(n) </tex>.
== Ссылки ==