Суффиксный автомат — различия между версиями
м (ё) |
(→Проверка вхождения строки) |
||
Строка 131: | Строка 131: | ||
Построим суффиксный автомат для строки <tex>s</tex>.<br> | Построим суффиксный автомат для строки <tex>s</tex>.<br> | ||
Пусть текущее состояние {{---}} <tex>\mathrm{cur}</tex>, изначально равно <tex>0</tex> (начальному состоянию).<br> | Пусть текущее состояние {{---}} <tex>\mathrm{cur}</tex>, изначально равно <tex>0</tex> (начальному состоянию).<br> | ||
− | Будем по очереди обрабатывать символы строки <tex>p</tex>. Если из состояния <tex>\mathrm{cur}</tex> есть переход в по текущему символу, | + | Будем по очереди обрабатывать символы строки <tex>p</tex>. Если из состояния <tex>\mathrm{cur}</tex> есть переход в по текущему символу, то перейдем в новое состояние и повторим процедуру. Если перехода не существует, то <tex>p</tex> не является подстрокой <tex>s</tex>. Если успешно обработали все символы <tex>p</tex>, то она является подстрокой <tex>s</tex>.<br>Асимптотика {{---}} построение суфавтомата за <tex>O(|s|)</tex>, проверка за <tex>O(|p|)</tex>. |
===Позиция первого вхождения строки=== | ===Позиция первого вхождения строки=== |
Версия 22:16, 5 марта 2018
Определение: |
Суффиксный автомат (англ. suffix automaton, directed acyclic word graph) — минимальный ДКА, который принимает все суффиксы строки и только их. |
Содержание
Описание
Рассмотрим конечный алфавит
. Пусть — набор слов в алфавите . Суффиксный автомат — это набор , где- — конечный набор состояний,
- — начальное состояние,
- — набор терминальных состояний,
- — функция перехода.
Для
и , определена, если состояние достижимо из переходом по символу . Функция перехода распространяется на слова и обозначает, что если она существует, то состояние достигнуто после чтения слова из состояния . Автомат распознает язык .Суффиксный автомат ациклический ориентированный граф, с начальной вершиной и множеством терминальных вершин, рёбра которого помечены символами :
для строки представляет собой- вершины этого графа — состояния автомата, а рёбра — переходы,
- каждый переход в автомате — ребро в графе, помеченное некоторым символом и все рёбра, исходящие из одной вершины имеют разные метки,
- одно из состояний называется начальным, из него достижимы все остальные состояния,
- одно или несколько состояний помечены как терминальные — если пройти от начального состояния до терминального по какому-либо пути и выписывать при этом символы на переходах, то получим один из суффиксов строки .
Определение: |
Состояние | принимает строку , если существует путь из начального состояния в , такой, что если последовательно выписать буквы на рёбрах на пути, получим строку .
Определение: |
Автомат принимает строку | , если её принимает хотя бы одно из финальных состояний.
Так как автомат детерминированный, то каждому пути соответствует строка.
Если две строки
и принимаются одним состоянием произвольного автомата, то для любой строки строки и принимаются или не принимаются автоматом одновременно. Действительно, независимо от того, как мы пришли в состояние , если мы пройдём из него по пути, соответствующему строке , мы сможем точно сказать, в какое состояние мы попадём (в частности, будет ли оно финальным). Значит, любому состоянию соответствует множество строк , которые переводят его в одно из конечных состояний.Определение: |
Множество | называют правым контекстом состояния.
Правый контекст определен не только для состояния, но и для строк, которые оно принимает — правый контекст строк совпадает с правым контекстом состояния.
Утверждение: |
Состояний в автомате не меньше, чем различных правых контекстов у подстрок строки, для которой он построен, причём в минимальном автомате достигается нижняя оценка. |
Допустим, что в автомате есть два состояния | и такие что . Мы можем удалить состояние и перевести переходы, ведущие в него в состояние . Множество принимаемых строк от этого не изменится, следовательно, мы можем продолжать, пока количество состояний не будет равно числу попарно различных правых контекстов.
Таким образом, ДКА является минимальным тогда и только тогда, когда правые контексты всех его состояний попарно различны. В случае суффиксного автомата правый контекст
строки взаимнооднозначно соответствует множеству правых позиций вхождений строки в строку . Таким образом, каждое состояние автомата принимает строки с одинаковым множеством правых позиций их вхождений и обратно, все строки с таким множеством позиций принимается этим состоянием.Построение
Алгоритм
Определение: |
Пусть длина самой короткой строки, которая принимается состоянием | равно , тогда суффиксная ссылка будет вести из этого состояния в состояние, которое принимает эту же строку без первого символа.
Будем обозначать длину самой длинной строки, которая принимается состоянием
Обозначим состояние , соответствующее текущей строке до добавления символа (изначально ).
Создадим новое состояние , .
Рассмотрим все переходы из по текущему символу . Если перехода нет, то добавляем переход в , переходим по суффиксной ссылке и повторяем процедуру снова. Если переход существует, то остановимся и обозначим текущее состояние за . Если перехода не нашлось и по суффиксным ссылкам мы дошли до фиктивного состояния (на которое указывает ), то .
Допустим, что мы остановились в состоянии , из которого существует переход с символом . Обозначим состояние, куда ведёт переход, через . Рассмотрим два случая:
- Если
- В противном случае, создадим новое состояние , скопируем в него вместе с суффиксными ссылками и переходами. присвоим значение . Перенаправим суффиксную ссылку из в и добавим ссылку из в . Пройдём по всем суффиксным ссылкам из состояния и все переходы в состояние по символу перенаправим в .
Обновим значение
.Пример построения
Изображение | Описание |
---|---|
Изначально автомат состоит из одного начального состояния. | |
Добавляем символ | . Создаем состояние . Переходов из начального состояния по символу нет, перейти по суффиксным ссылкам некуда, значит добавим суффиксную ссылку .|
Добавляем символ | . Создаем состояние . Добавим переход из , откатимся по суффиксной ссылке и добавим переход из . Добавим суффиксную ссылку .|
Аналогично добавим символ | и обновим автомат.|
Добавляем символ | . Добавим переход из и перейдем по суффиксной ссылке в начальное состояние. Из состояния существует переход по символу|
Рассмотрим состояние
| , куда существует переход. Имеем .
|
Построение автомата завершено. Чтобы пометить терминальные вершины, найдём состояние, которое принимает строку | и пройдём по суффиксным ссылкам, помечая все посещенные состояния терминальными.
Реализация
В приведённой ниже реализации используются следующие переменные:
- — массив отображений (ключ — символ, значение — номер состояния) с переходами,
- — массив суффиксных ссылок,
- — массив длин строк,
- — функция, которая создаёт новое состояние и возвращает его номер,
- — функция, которая копирует состояние и возвращает номер нового состояния,
- — последнее состояние.
func addChar(c : char):
int cur = newState() // создаём новое состояние и получаем его номер
int p = last
while p >= 0 and edges[p].find(c) == null
edges[p][c] = cur
p = link[p]
if p != -1
int q = edges[p][c]
if len[p] + 1 == len[q]
link[cur] = q
else
int new = clone(q) // скопируем состояние
и получим номер нового состояния
len[new] = len[p] + 1
link[q] = link[cur] = new
while p >= 0 and edges[p][c] == q
edges[p][c] = new
p = link[p]
last = cur
Применение
Проверка вхождения строки
Задача: |
Даны строки | и . Требуется проверить, является ли строка подстрокой .
Построим суффиксный автомат для строки
Пусть текущее состояние — , изначально равно (начальному состоянию).
Будем по очереди обрабатывать символы строки . Если из состояния есть переход в по текущему символу, то перейдем в новое состояние и повторим процедуру. Если перехода не существует, то не является подстрокой . Если успешно обработали все символы , то она является подстрокой .
Асимптотика — построение суфавтомата за , проверка за .
Позиция первого вхождения строки
Задача: |
Даны строки | и . Требуется найти позицию первого вхождения строки в .
Построим суффиксный автомат для строки
В процессе построения для каждого состояния будем хранить значение — позицию окончания первого вхождения строки.
Поддерживать позицию можно следующим образом: при добавлении нового состояния , а при клонировании вершины .
Для поиска вхождения обойдём автомат, как в предыдущей задаче. Пусть состояние в автомате соответствует строке . Тогда ответ на задачу .
Асимптотика — построение суфавтомата за , проверка за .
Количество различных подстрок
Задача: |
Дана строка | . Найти количество различных подстрок строки .
Построим суффиксный автомат для строки
Каждой подстроке в суффиксном автомате соответствует путь, тогда ответ на задачу — количество различных путей из начальной вершины. Так как суфавтомат представляет собой ациклический граф, мы можем найти количество путей в графе методом динамического программирования.
Наибольшая общая подстрока двух строк
Задача: |
Даны строки | и . Требуется найти наибольшую общую подстроку двух строк.
Построим суффиксный автомат для строки
Пройдём по строке и для текущего символа будем искать длину наибольшей общей подстроки, которая заканчивается в текущей позиции. Для этого будем поддерживать — текущее состояние и — текущую длину совпадающей части.
Изначально , — совпадение пустое. Рассматриваем текущий символ . Если в автомате существует переход из текущего состояния по данному символу, то перейдем в новое состояние и увеличим длину на .
Если перехода не существует, то попробуем минимально уменьшить длину совпадающей подстроки: перейдем по суффиксной ссылке из в новое состояние и примем . Повторим операцию до тех пор, пока не найдём переход. Если по суффиксным ссылкам мы дошли до состояния, в которое ведёт суффиксная ссылка начальной вершины, то это значит, что символа нет в строке . В таком случае примем , после чего перейдем к следующему символу строки .
Длиной наибольшей общей подстроки будет — максимум из всех значений , полученных в ходе работы алгоритма. Тогда ответом на задачу будет являться подстрока , где — позиция, в которой достигнут максимум.
Сравнение с другими суффиксными структурами
Пусть алфавит.
— строка, для которой строим соответствующую структуру, , —Время работы | Память | |
Суффиксный бор | ||
Сжатое суффиксное дерево | ||
Суффиксный массив | ||
Суффиксный автомат |
См. также
- Автомат для поиска образца в тексте
- Алгоритм Ахо-Корасик
- Поиск наибольшей общей подстроки двух строк с использованием хеширования
Источники информации
- Maxime Crochemore, Christophe Hancart, Thierry Lecroq — Algorithms on Strings
- А. Кульков — Лекция по суффиксным структурам
- MAXimal :: algo :: Суффиксный автомат