Сжатое суффиксное дерево
Суффиксный бор — удобная структура данных для поиска подстроки в строке, но она занимает много места в памяти. Рассмотрим в боре все пути от до , в которых у каждой вершины только один сын. Такой путь можно сжать до ребра , записав на нем все встречающиеся на пути символы. Получилось сжатое суффиксное дерево.
Содержание
Определение
Суффиксное дерево (сжатое суффиксное дерево) для строки (где ) — дерево с листьями, каждая внутренняя вершина которого имеет не меньше двух детей, а каждое ребро помечено непустой подстрокой строки и символом ее начала. Два ребра, выходящие из одной вершины, не могут иметь одинаковых символьных меток. Такое дерево, как и суффиксный бор, содержит все суффиксы строки , причем каждый суффикс заканчивается точно в листе и нигде кроме него.
Защитный символ
По определению суффиксное дерево существует не для любой строки : если один суффикс строки совпадает с префиксом другого, то построить такое суффиксное дерево невозможно. Например, для строки суффикс является префиксом суффикса Для решения проблемы в конце строки добавляется символ, не входящий в исходный алфавит: защитный символ. Как правило, это . Любой суффикс строки с защитным символом действительно заканчивается в листе и только в листе.
Далее - длина строки с защитным символом.
Хранение суффиксного дерева
Заметим, что для хранения на ребре подстроки используют индексы ее начала и конца в исходной строке и не хранят саму строку. Теперь представим дерево как массив , где — количество вершин в дереве, - мощность алфавита. Каждая ячейка содержит информацию о том, в какую вершину ведет ое ребро по ому символу и индексы . Такое дерево занимает памяти.
Количество вершин
В сжатом суффиксном дереве содержится листьев, т.к. строка содержит ровно суффиксов. Рассмотрим теперь количество внутренних вершин такого дерева.
| Лемма: |
Количество внутренних вершин дерева, каждая из которых имеет не менее двух детей, меньше количества листьев. |
| Доказательство: |
|
Докажем лемму индукцией по количеству листьев . База При в дереве одна внутренняя вершина - верно. Переход Рассмотрим все вершины в дереве для строки длины , у которых хотя бы один из детей - лист. Если среди них есть вершина, у которой более двух детей, отрежем от нее лист. Получим дерево с листьями, удовлетворяющее условию леммы по индукционному предположению, причем в нем количество внутренних вершин равно количеству внутренних вершин в исходном дереве. Тогда у полученного дерева менее внутренних вершин, значит в исходном дереве количество внутренних вершин меньше количества листьев. Иначе среди этих вершин есть вершина, у которой оба ребенка - листья. Отрежем оба этих листа, получим дерево с листьями, удовлетворяющее условию леммы, количество внутренних вершин которого на меньше количества внутренних вершин в исходном дереве. Тогда, по индукционному предположению, у полученного дерева менее внутренних вершин, значит в исходном дереве количество внутренних вершин меньше . |
Занимаемая память
Так как любое суффиксное дерево удовлетворяет условиям леммы (у каждой вершины не менее двух детей), то количество внутренних вершин в нем меньше количества листьев, равного . Значит, для его хранения требуется памяти.
Построение суффиксного дерева
Рассмотрим наивный алгоритм построения суффиксного дерева:
for to do //для каждого символа строки insert() //добавляем суффикс, начинающийся с него
insert(l,r)
//инициализируем текущую вершину корнем
while ()
if //если мы не можем пойти из вершины по символу
create_vertex() //создаем новую вершину
else
for to //для каждого символа на ребре из текущей вершины
if //если нашли не совпадающий символ
разбить ребро
break
if ребро не разбивали
//переходим по ребру
//двигаемся по суффиксу на длину подстроки, записанной на ребре
Этот алгоритм работает за время , однако существует алгоритм Укконена, позволяющий построить дерево за время .
Использование сжатого суффиксного дерева
Суффиксное дерево позволяет за линейное время найти:
- Количество различных подстрок данной строки
- Наибольшую общую подстроку двух строк
- Суффиксный массив и массив (longest common prefix) исходной строки
Источники
- Дэн Гасфилд — Строки, деревья и последовательности в алгоритмах: Информатика и вычислительная биология — СПб.: Невский Диалект; БХВ-Петербург, 2003. — 654 с: ил.