Алгоритм Укконена — различия между версиями
| Строка 107: | Строка 107: | ||
При переходе по суффиксной ссылке глубина уменьшается не более чем на 1. | При переходе по суффиксной ссылке глубина уменьшается не более чем на 1. | ||
|proof= | |proof= | ||
| − | Пусть мы переходим из вершины <tex> v </tex> с путевой меткой <tex>t_i ... t_j</tex> по суффиксной ссылке в вершину <tex> u </tex> с путевой меткой <tex>t_{i + 1} ... tj</tex> Определим множество <tex> A </tex> как множество вершин на пути от корня до <tex> u </tex>, исключая корень. Множество <tex> B </tex> определим как множество вершин на пути от корня до <tex> v </tex>, исключая корень. Если длина первого ребра на пути от корня до <tex> v </tex> равна единице, то выкинем из множества <tex>B</tex> вершину, в которую ведет это ребро. Итого по построению получаем: <tex></tex> | + | Пусть мы переходим из вершины <tex> v </tex> с путевой меткой <tex>t_i ... t_j</tex> по суффиксной ссылке в вершину <tex> u </tex> с путевой меткой <tex>t_{i + 1} ... tj</tex> Определим множество <tex> A </tex> как множество вершин на пути от корня до <tex> u </tex>, исключая корень. Множество <tex> B </tex> определим как множество вершин на пути от корня до <tex> v </tex>, исключая корень. Если длина первого ребра на пути от корня до <tex> v </tex> равна единице, то выкинем из множества <tex>B</tex> вершину, в которую ведет это ребро. Итого по построению получаем: <tex>|A| = d(u)</tex>, <tex>|B| \ge d(v) - 1</tex>. Теперь заметим, что суффиксная ссылка из любой вершины множества <tex>B</tex> ведет в некоторую вершину множества <tex> A</tex>, и очевидно суффиксные ссылки из разных вершин ведут в разные вершины, поэтому <tex>|A| \ge |B|</tex>, а значит <tex>d(u) \ge d(v) - 1</tex> |
}} | }} | ||
Версия 01:05, 6 мая 2011
Алгоритм Укконена — алгоритм построения суффиксного дерева для заданной строки за линейное время.
Содержание
Первая версия алгоритма
Рассмотрим сначала метод, который строит дерево за время , где — длина исходной строки . В дальнейшем данный алгоритм будет оптимизирован таким образом, что будет достигнута линейная скорость работы.
Описание
Алгоритм делится на фаз. В фазе с номером в дерево добавляются все суффиксы подстроки . При добавлении суффикса алгоритм сначала находит конец пути из корня, помеченного подстрокой , затем добавляет к найденной вершине новое ребро с листом , если этот символ не был добавлен ранее.
Псевдокод
Приведенный алгоритм можно записать с помощью псевдокода:
for to do for to do insert()
Поскольку операция insert может занимать линейное время, очевидно, что время работы данного алгоритма составляет .
Возможные исходы операции insert
Ниже приведены три возможных случая, которые могут возникнуть при добавлении подстроки в дерево.
Оптимизация алгоритма Укконена
Рассмотрим две леммы, позволяющие ускорить алгоритм Укконена до .
Лемма 1. Стал листом — листом и останешься
| Лемма: |
Если в какой-то момент работы алгоритма Укконена будет создан лист с меткой (для суффикса, начинающегося в позиции строки ), он останется листом во всех последовательных деревьях, созданных алгоритмом.
|
| Доказательство: |
| Это верно потому, что у алгоритма нет механизма продолжения листового ребра дальше текущего листа. Если есть лист с суффиксом , правило продолжения 1 будет применяться для продолжения на всех последующих фазах. |
Лемма 2. Правило 3 заканчивает дело
| Лемма: |
В любой фазе, если правило продолжения 3 применяется в продолжении , оно будет реализовываться во всех дальнейших продолжениях(от по ) до конца фазы.
|
| Доказательство: |
| При использовании правила продолжения 3 путь, помеченный в текущем дереве, должен продолжаться символом , и точно так же продолжается путь, помеченный , поэтому правило 3 применяется в продолжениях |
Когда используется правило 3, никакой работы делать не нужно, так как требуемый суффикс уже в дереве есть. Поэтому можно заканчивать каждую фазу после первого же использования правила прохождения 3. Если это случится в продолжении j, то уже не требуется явно находить концы строк с .
Алгоритм Укконена за квадратичное время
Рассмотрим правила продолжения суффиксов.
При использовании правила 1 по лемме 1 в последующих фазах будет выполняться правило 1. Поэтому скажем, что мы создаём лист не только для рассмотренной части строки, а для всей всей строки до конца.
При использовании правила 2 появится новый лист, который далее будет продлеваться по правилу 1.
При использовании правила 3 по лемме 2 никакой работы делать не нужно, поскольку суффикс в дереве уже есть. Следовательно, можно остановиться и не добавлять следующие суффиксы.
Таким образом, операция insert позволяет суффиксы не только для подстрок , но и сразу для всего суффикса .
Псевдокод
Приведенный алгоритм можно записать с помощью псевдокода:
for to do insert()
Поскольку операция insert по-прежнему занимает линейное время, очевидно, что время работы данного алгоритма составляет .
Суффиксные ссылки
| Определение: |
| Пусть обозначает произвольную строку, где — ее первый символ, а — оставшаяся подстрока(возможно пустая). Если для внутренней вершины с путевой меткой существует другая вершина с путевой меткой то ссылка из в называется суффиксной ссылкой. |
Лемма 1. Существование суффиксных ссылок
| Лемма: |
Для любой внутренней вершины суффиксного дерева существует суффиксная ссылка, ведущая в некоторую внутреннюю вершину . |
| Доказательство: |
| Рассмотрим внутренную вершину с путевой меткой . Так как эта вершина внутренняя, ее путевая метка ветвится справа в исходной строке. Тогда очевидно подстрока тоже ветвится справа в исходной строке, и ей соответствует некоторая внутренняя вершина . По определению суффиксная ссылка вершины ведет в |
Построение суффиксных ссылок
Заметим что в процессе построения суффиксного дерева уже построенные суффиксные ссылки никак не изменяются. Опишем процесс построения суффиксной ссылки для новой созданной внутренней вершины. Пусть в результате очередного продления была создана новая внутренняя вершина с путевой меткой . Перейдем к следущему шагу текущей фазы, на котором в дерево будет добавлен суффикс соответствующий вершине (возможно до продления суффикс оканчивался на ребре, но в этом случае по рассуждениям аналогичным Лемме 1 будет создана новая внутрення вершина). По определению суффиксная ссылка из вершины ведет в .
Использование суффиксных ссылок
Опишем как искать концы суффиксов в дереве, которые нужно продлить. Пусть мы только что продлили суффикс . Найдем с помощью построенных ссылок конец суффикса . Пройдем вверх по дереву от конца суффикса до ближайшей внутренней вершины . Ей соответствует некоторая подстрока . У вершины есть суффиксная ссылка, так как ссылка для новой внутренней вершины строится внутри фазы ее создания. Пусть суффиксная ссылка ведет в вершину , которой соответствует подстрока . Теперь пройдем от вершины пройдем вниз по дереву, читая текст , и придем к концу суффикса .
Оценка числа переходов
| Определение: |
| Глубиной вершины назовем число ребер на пути от корня до вершины |
| Лемма: |
При переходе по суффиксной ссылке глубина уменьшается не более чем на 1. |
| Доказательство: |
| Пусть мы переходим из вершины с путевой меткой по суффиксной ссылке в вершину с путевой меткой Определим множество как множество вершин на пути от корня до , исключая корень. Множество определим как множество вершин на пути от корня до , исключая корень. Если длина первого ребра на пути от корня до равна единице, то выкинем из множества вершину, в которую ведет это ребро. Итого по построению получаем: , . Теперь заметим, что суффиксная ссылка из любой вершины множества ведет в некоторую вершину множества , и очевидно суффиксные ссылки из разных вершин ведут в разные вершины, поэтому , а значит |
Источник
Дэн Гасфилд — Строки, деревья и последовательности в алгоритмах: Информатика и вычислительная биология — СПб.: Невский Диалект; БХВ-Петербург, 2003. — 654 с: ил.


