Алгоритм Укконена — различия между версиями
Kot (обсуждение | вклад) (добавлено две леммы) |
Kot (обсуждение | вклад) |
||
Строка 39: | Строка 39: | ||
Рассмотрим две леммы, позволяющие ускорить алгоритм Укконена до <tex>O(n^2)</tex>. | Рассмотрим две леммы, позволяющие ускорить алгоритм Укконена до <tex>O(n^2)</tex>. | ||
− | + | <br /> | |
===Лемма 1. Стал листом {{---}} листом и останешься === | ===Лемма 1. Стал листом {{---}} листом и останешься === | ||
{{Лемма | {{Лемма | ||
|statement= | |statement= | ||
Если в какой-то момент работы алгоритма Укконена будет создан лист с меткой <tex>j</tex> (для суффикса, начинающегося в позиции <tex>j</tex> строки <tex>S</tex>), он останется листом во всех последовательных деревьях, созданных алгоритмом. | Если в какой-то момент работы алгоритма Укконена будет создан лист с меткой <tex>j</tex> (для суффикса, начинающегося в позиции <tex>j</tex> строки <tex>S</tex>), он останется листом во всех последовательных деревьях, созданных алгоритмом. | ||
− | + | <br /> | |
|proof= | |proof= | ||
Это верно потому, что у алгоритма нет механизма продолжения листового ребра дальше текущего листа. Если есть лист с суффиксом <tex>j</tex>, правило продолжения 1 будет применяться для продолжения <tex>j</tex> на всех последующих фазах. | Это верно потому, что у алгоритма нет механизма продолжения листового ребра дальше текущего листа. Если есть лист с суффиксом <tex>j</tex>, правило продолжения 1 будет применяться для продолжения <tex>j</tex> на всех последующих фазах. | ||
Строка 53: | Строка 53: | ||
|statement= | |statement= | ||
В любой фазе, если правило продолжения 3 применяется в продолжении <tex>о</tex>, оно будет реализовываться во всех дальнейших продолжениях(от <tex>j + 1</tex> по <tex>i + 1</tex>) до конца фазы. | В любой фазе, если правило продолжения 3 применяется в продолжении <tex>о</tex>, оно будет реализовываться во всех дальнейших продолжениях(от <tex>j + 1</tex> по <tex>i + 1</tex>) до конца фазы. | ||
− | + | <br /> | |
|proof= | |proof= | ||
При использовании правила продолжения 3 путь, помеченный <tex>S[j..i]</tex> в текущем дереве, должен продолжаться символом <tex>i+1</tex>, и точно так же продолжается путь, помеченный <tex>S[j + 1..i]</tex>, поэтому правило 3 применяется в продолжениях <tex>j + 1, j + 2, ..., i + 1</tex> | При использовании правила продолжения 3 путь, помеченный <tex>S[j..i]</tex> в текущем дереве, должен продолжаться символом <tex>i+1</tex>, и точно так же продолжается путь, помеченный <tex>S[j + 1..i]</tex>, поэтому правило 3 применяется в продолжениях <tex>j + 1, j + 2, ..., i + 1</tex> | ||
}} | }} | ||
− | Когда используется правило 3, никакой работы делать не нужно, так как требуемый суффикс уже в дереве есть | + | <br /> |
+ | Когда используется правило 3, никакой работы делать не нужно, так как требуемый суффикс уже в дереве есть. Поэтому можно заканчивать каждую фазу <tex>i + 1</tex> после первого же использования правила прохождения 3. Если это случится в продолжении j, то уже не требуется явно находить концы строк <tex>S[k..i]</tex> с <tex>k > j</tex>. | ||
+ | |||
+ | ==Алгоритм Укконена за квадратичное время== | ||
+ | |||
+ | Рассмотрим правила продолжения суффиксов. | ||
+ | |||
+ | При использовании правила 1 по лемме 1 в последующих фазах будет выполняться правило 1. Поэтому скажем, что мы создаём лист не только для рассмотренной части строки, а для всей всей строки до конца. <br /> | ||
+ | При использовании правила 2 появится новый лист, который далее будет продлеваться по правилу 1. <br /> | ||
+ | При использовании правила 3 по лемме 2 никакой работы делать не нужно, поскольку суффикс в дереве уже есть. Следовательно, можно остановиться и не добавлять следующие суффиксы. | ||
+ | Таким образом, операция insert позволяет суффиксы не только для подстрок <tex>S[j..i]</tex>, но и сразу для всего суффикса <tex>S[j..n]</tex>. | ||
+ | === Псевдокод === | ||
+ | Приведенный алгоритм можно записать с помощью псевдокода: | ||
+ | '''for''' <tex> i \leftarrow 1 </tex> '''to''' <tex> n </tex> '''do''' | ||
+ | insert(<tex>s_{i..n}</tex>) | ||
+ | Поскольку операция insert по-прежнему занимает линейное время, очевидно, что время работы данного алгоритма составляет <tex>O(n^2)</tex>. | ||
==Суффиксные ссылки== | ==Суффиксные ссылки== |
Версия 22:43, 21 марта 2011
Алгоритм Укконена — алгоритм построения суффиксного дерева для заданной строки за линейное время.
Содержание
Первая версия алгоритма
Рассмотрим сначала метод, который строит дерево за время
, где — длина исходной строки . В дальнейшем данный алгоритм будет оптимизирован таким образом, что будет достигнута линейная скорость работы.Описание
Алгоритм делится на
фаз. В фазе с номером в дерево добавляются все суффиксы подстроки . При добавлении суффикса алгоритм сначала находит конец пути из корня, помеченного подстрокой , затем добавляет к концу этой подстроки очередной символ , если этот символ не был добавлен ранее.Псевдокод
Приведенный алгоритм можно записать с помощью псевдокода:
forto 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 позволяет суффиксы не только для подстрок
, но и сразу для всего суффикса .Псевдокод
Приведенный алгоритм можно записать с помощью псевдокода:
forto do insert( )
Поскольку операция insert по-прежнему занимает линейное время, очевидно, что время работы данного алгоритма составляет
.Суффиксные ссылки
Определение: |
Пусть | обозначает произвольную строку, где — ее первый символ, а — оставшаяся подстрока(возможно пустая). Если для внутренней вершины с путевой меткой существует другая вершина с путевой меткой то ссылка из в называется суффиксной ссылкой.
Источник
Дэн Гасфилд — Строки, деревья и последовательности в алгоритмах: Информатика и вычислительная биология — СПб.: Невский Диалект; БХВ-Петербург, 2003. — 654 с: ил.