Алгоритм Касаи и др. — различия между версиями
(→Описание алгоритма) |
|||
Строка 1: | Строка 1: | ||
'''Алгоритм Касаи''' (Аримуры-Арикавы-Касаи-Ли-Парка) {{---}} алгоритм, позволяющий за линейное время вычислить | '''Алгоритм Касаи''' (Аримуры-Арикавы-Касаи-Ли-Парка) {{---}} алгоритм, позволяющий за линейное время вычислить | ||
значения наибольших общих префиксов для соседних циклических сдвигов строки, отсортированных в лексикографическом | значения наибольших общих префиксов для соседних циклических сдвигов строки, отсортированных в лексикографическом | ||
− | порядке (largest common prefix, далее <tex> | + | порядке (largest common prefix, далее <tex>LCP</tex>). |
==Обозначения== | ==Обозначения== | ||
− | <tex> | + | Задана строка <tex>A</tex>. Тогда <tex>A_{i}</tex> {{---}} суфикс строки <tex>A</tex>, начинающийся в <tex>i</tex>-ом символе. Пусть задан суфиксный массив <tex>Pos</tex>. Для вычисления <tex>LCP</tex> будем использовать промежуточный массив <tex>Rank</tex>. Массив <tex>Rank</tex> определен как обратный к массиву <tex>Pos</tex>. Он может быть получен немедленно, если задан массив <tex>Pos</tex>. Если <tex>Pos[k] = i</tex>, то <tex>Rank[i] = k</tex>. |
− | <tex> | + | <tex>Height[i]</tex> {{---}} длина наибольшего общего префикса <tex>i</tex> и <tex>i-1</tex> строк в суффиксном массиве (<tex>Pos[i]</tex> и <tex>Pos[i-1]</tex> соответственно). |
− | <tex> | + | ==Некоторые свойства <tex>LCP</tex>== |
− | + | ===Факт №1=== | |
+ | <tex>LCP</tex> между двумя суфиксами {{---}} это минимум <tex>LCP</tex> всех пар смежных суфиксов между ними в суфиксном массиве <tex>Pos</tex>. То есть <tex>LCP(A_{Pos[x]}, A_{Pos[z]}) = min_{x < y \le z}(LCP(A_{Pos[y - 1]},A_{Pos[y]})</tex>. | ||
+ | Отсюда следует, что <tex>LCP</tex> пары соседних суфиксов в массиве <tex>Pos</tex> больше или равно <tex>LCP</tex> пары суфиксов, окружающих их. | ||
− | + | {{Утверждение | |
+ | |statement=<tex>LCP(A_{Pos[y - 1]}, A_{Pos[y]}) \le LCP(A_{Pos[x]},A_{Pos[z]}), x < y \le z</tex> | ||
+ | }} | ||
− | == | + | ===Факт №2=== |
− | + | Если значение <tex>LCP</tex> между парой соседних суфиксов, смежных в массиве <tex>Pos</tex> больше <tex>1</tex>, то лексикографический порядок суффиксов сохранится, если удалить первый символ каждого суффикса.<br> | |
− | + | {{Утверждение | |
− | + | |statement= | |
+ | Если <tex>LCP(A_{Pos[x-1]} , A_{Pos[x]} ) > 1</tex>, тогда <tex>Rank[Pos[x - 1] + 1] < Rank[Pos[x] + 1]</tex> | ||
+ | }} | ||
+ | ===Факт №3=== | ||
+ | В этом же случае, значение <tex>LCP</tex> между <tex>A_{Pos[x-1]+1}</tex> и <tex>A_{Pos[x]+1}</tex> на один меньше значения <tex>LCP</tex> между <tex>A_{Pos[x-1]}</tex> и <tex>A_{Pos[x]}</tex>.<br> | ||
+ | {{Утверждение | ||
+ | |statement=Если <tex>LCP(A_{Pos[x-1]} , A_{Pos[x]} ) > 1</tex>, тогда <tex>LCP(A_{Pos[x-1]+1} , A_{Pos[x]+1}) = LCP(A_{Pos[x-1]} , A_{Pos[x]} ) - 1</tex> | ||
+ | }} | ||
+ | |||
+ | Теперь рассмотрим следующую задачу: расчитать <tex>LCP</tex> между суфиксом <tex>A_{i}</tex> и его смежным суфиксом в массиве <tex>Pos</tex>, при условии, что значение <tex>LCP</tex> между <tex>A_{i-1}</tex> и его смежным суфиксом известны. Для удобства записи пусть <tex>p=Rank[i - 1]</tex> и <tex>q = Rank[i]</tex>. Так же пусть <tex>j - 1 = Pos[p-1]</tex> и <tex>k = Pos[q - 1]</tex>. Проще говоря, мы хотим посчитать <tex>Height[q]</tex>, когда задано <tex>Height[p]</tex> | ||
+ | |||
+ | {{Лемма|statement= | ||
+ | Если <tex>LCP(A_{j-1}, A_{i-1}) > 1</tex>, тогда <tex>LCP(A_k,A_i) \le LCP(A_j,A_i)</tex> | ||
+ | |proof= | ||
+ | Так как <tex>LCP(A_{j−1},A_{i−1}) > 1</tex>, имеем <tex>Rank[j] < Rank[i]</tex> из факта №2. Так как <tex>Rank[j] \le Rank[k] = Rank[i] - 1</tex>, имеем <tex>LCP(A_{k} , A_{i}) \ge LCP(A_{j} , A_{i})</tex> из факта №1 | ||
+ | }} | ||
{{Теорема|statement= | {{Теорема|statement= | ||
− | Если <tex> | + | Если <tex>Height[p] = lcp(A_{j-1}, A_{i-1}) > 1</tex>, то <tex>Height[q] = lcp(A_{k}, A_{i}) \ge Height[p] - 1</tex> |
|proof= | |proof= | ||
− | <tex> | + | <tex>LCP(A_{k}, A_{i}) \ge LCP(A_{j} , A_{i})</tex>(из Леммы) = <tex>LCP(A_{j-1}, A_{i−1}) - 1</tex> (из факта №3). |
− | |||
− | |||
− | |||
− | |||
− | |||
}} | }} | ||
+ | ==Описание алгоритма== | ||
Таким образом, начиная проверять <tex>lcp</tex> для текущего суффикса не с первого символа, а с указанного, можно за линейное время построить <tex>lcp</tex>. | Таким образом, начиная проверять <tex>lcp</tex> для текущего суффикса не с первого символа, а с указанного, можно за линейное время построить <tex>lcp</tex>. | ||
Покажем, что построение <tex>lcp</tex> таким образом действительно требует <tex>O(N)</tex> времени. Действительно, на каждой итерации текущее значение <tex>lcp</tex> может быть не более | Покажем, что построение <tex>lcp</tex> таким образом действительно требует <tex>O(N)</tex> времени. Действительно, на каждой итерации текущее значение <tex>lcp</tex> может быть не более |
Версия 20:47, 16 апреля 2012
Алгоритм Касаи (Аримуры-Арикавы-Касаи-Ли-Парка) — алгоритм, позволяющий за линейное время вычислить значения наибольших общих префиксов для соседних циклических сдвигов строки, отсортированных в лексикографическом порядке (largest common prefix, далее
).Содержание
Обозначения
Задана строка
. Тогда — суфикс строки , начинающийся в -ом символе. Пусть задан суфиксный массив . Для вычисления будем использовать промежуточный массив . Массив определен как обратный к массиву . Он может быть получен немедленно, если задан массив . Если , то .— длина наибольшего общего префикса и строк в суффиксном массиве ( и соответственно).
Некоторые свойства
Факт №1
между двумя суфиксами — это минимум всех пар смежных суфиксов между ними в суфиксном массиве . То есть . Отсюда следует, что пары соседних суфиксов в массиве больше или равно пары суфиксов, окружающих их.
Утверждение: |
Факт №2
Если значение
Утверждение: |
Если , тогда |
Факт №3
В этом же случае, значение
Утверждение: |
Если , тогда |
Теперь рассмотрим следующую задачу: расчитать
между суфиксом и его смежным суфиксом в массиве , при условии, что значение между и его смежным суфиксом известны. Для удобства записи пусть и . Так же пусть и . Проще говоря, мы хотим посчитать , когда заданоЛемма: |
Если , тогда |
Доказательство: |
Так как | , имеем из факта №2. Так как , имеем из факта №1
Теорема: |
Если , то |
Доказательство: |
(из Леммы) = (из факта №3). |
Описание алгоритма
Таким образом, начиная проверять
для текущего суффикса не с первого символа, а с указанного, можно за линейное время построить . Покажем, что построение таким образом действительно требует времени. Действительно, на каждой итерации текущее значение может быть не более чем на единицу меньше предыдущего. Таким образом, значения в сумме могут увеличиться не более, чем на (с точностью до константы). Следовательно, алгоритм построит за .Источники
1. Алгоритм Касаи.
2. T.Kasai, G.Lee, H.Arimura, S.Arikawa, K.Park - Linear-Time Longest-Common-Prefix Computation in Suffix Arrays and Its Application.