Алгоритм Фараха — различия между версиями
Slavian (обсуждение | вклад) (→шаг 1: построение четного дерева) |
Slavian (обсуждение | вклад) (→шаг 3: слияние четного и нечетного дерева) |
||
Строка 92: | Строка 92: | ||
== шаг 3: слияние четного и нечетного дерева == | == шаг 3: слияние четного и нечетного дерева == | ||
+ | |||
+ | Далее необходимо найти эффективный способ слияния нечетного и четного деревьев в одно дерево <tex>Т_s</tex>. Слияние будем производить начиная с корня. | ||
+ | Предположим, что для каждого узла деревьев <tex>Т_s^{odd}</tex> и <tex>Т_s^{even}</tex> выходящие из них ребра занесены в специальные списки, где они упорядочены в возрастающем лексикографическом порядке подстрок, которые представляют эти | ||
+ | ребра. Алгоритм слияния деревьев просматривает только первые буквы подстрок, представленных ребрами деревьев <tex>Т_s^{odd}</tex> и <tex>Т_s^{even}</tex>, пусть это будут буквы <tex>\lambda^{odd}</tex> и <tex>\lambda^{even}</tex>. Тогда: | ||
+ | * если <tex>\lambda^{odd}</tex> <tex>\ne</tex> <tex>\lambda^{even}</tex>, определяется поддерево, соответствующее меньшей из этих букв, и без изменений присоединяется к узлу-родителю; | ||
+ | * если <tex>\lambda^{odd}</tex> <tex>=</tex> <tex>\lambda^{even}</tex> и длины подстрок, представленных соответствующими ребрами, равны, в дерево слияния к текущему узлу добавляются два сына: один — из четного дерева, другой — из нечетного; | ||
+ | * если <tex>\lambda^{odd}</tex> <tex>=</tex> <tex>\lambda^{even}</tex> и длины подстрок, представленных соответствующими ребрами, различны, в дерево слияния к текущему узлу добавляются два узла, находящиеся на одном нисходящем пути, при этом ближайший узел будет соответствовать более короткой подстроке. | ||
+ | |||
+ | Если начать эту процедуру для корней нечетного и четного деревьев, далее она рекурсивно выполняется для корней всех поддеревьев, которые, возможно, уже содержат узлы из нечетного и четного деревьев, поскольку ранее мог быть реализован случай <tex>\lambda^{odd}</tex> <tex>=</tex> <tex>\lambda^{even}</tex>. Так как время манипулирования с любым ребром этих деревьев фиксированно, то общее время слияния деревьев составит <tex>O(N)</tex>. | ||
+ | |||
+ | В результате описанных действий получится дерево <tex>M_x</tex>,в котором будут присутствовать поддеревья, которые прошли процедуру сличния, и которые ее избежали (т.е были перенесены в дерево <tex>M_x</tex> без изменений). | ||
+ | |||
== шаг 4: построение LCP-дерева == | == шаг 4: построение LCP-дерева == | ||
== шаг 5: построение суффиксного дерева по LCP и слитому == | == шаг 5: построение суффиксного дерева по LCP и слитому == |
Версия 15:02, 13 мая 2014
Алгоритм Фарача — алгоритм построения суффиксного дерева для заданной строки , который выполняется за время , при этом даже не требуется выполнения условия конечности алфавита. Такая эффективность достигается за счет того, что строковые последовательности определяются на индексированном алфавите или, что эквивалентно, на целочисленном алфавите , при этом накладывается дополнительное условие, что . Такие алфавиты часто встречаются на практике.
описание алгоритма
Основная идея алгоритма, заключается в том что мы уменьшаем размер исходной строки. Для этого мы разбиваем символы сходной строки на пару и пронумеровываем их, а из полученных номеров составляем новую строку, которая уже в 2 раза короче.
Мы опишем алгоритм Фарача в виде пяти выполняемых шагов. Используем в качестве примера строку
, определенную на алфавите (в этом примере N = 12).шаг 0: суффиксное дерево для сжатой строки
* Строкаразбивается на пары: * Пары сортирутся поразрядной сортировкой: . * Удаляются копии: . * Парам даются номера (условно, в массиве они и так есть): * Создаётся новая строка из номеров пар: 1 0 1 2 3 2 * Из полученной строки создаётся суффикcное дерево:
ID | LCP | STR |
---|---|---|
1 | 0 | 0 1 2 3 2 |
0 | 0 | 1 0 1 2 3 2 |
2 | 1 | 1 2 3 2 |
3 | 0 | 2 3 2 |
5 | 1 | 2 |
4 | 0 | 3 2 |
шаг 1: построение четного дерева
Определение: |
Четное дерево | является деревом суффиксов для строки , узлы-листья которого ограничены нечетными позициями строки .
Из дерева сжатой строки получаем частичное (чётное) дерево исходной строки. Частичное потому в нём будут только половина суффиксов, т.е. тех которые стоят в чётных позициях. :
ID | LCP | STR |
---|---|---|
2 | 0 | 1112212221 |
0 | 1 | 121112212221 |
4 | 2 | 12212221 |
6 | 0 | 212221 |
10 | 2 | 21 |
8 | 1 | 2221 |
шаг 2: построение нечетного по четному
Определение: |
Нечетное дерево | является деревом суффиксов для строки , узлы-листья которого ограничены нечетными позициями строки .
шаг 3: слияние четного и нечетного дерева
Далее необходимо найти эффективный способ слияния нечетного и четного деревьев в одно дерево
. Слияние будем производить начиная с корня. Предположим, что для каждого узла деревьев и выходящие из них ребра занесены в специальные списки, где они упорядочены в возрастающем лексикографическом порядке подстрок, которые представляют эти ребра. Алгоритм слияния деревьев просматривает только первые буквы подстрок, представленных ребрами деревьев и , пусть это будут буквы и . Тогда:- если , определяется поддерево, соответствующее меньшей из этих букв, и без изменений присоединяется к узлу-родителю;
- если и длины подстрок, представленных соответствующими ребрами, равны, в дерево слияния к текущему узлу добавляются два сына: один — из четного дерева, другой — из нечетного;
- если и длины подстрок, представленных соответствующими ребрами, различны, в дерево слияния к текущему узлу добавляются два узла, находящиеся на одном нисходящем пути, при этом ближайший узел будет соответствовать более короткой подстроке.
Если начать эту процедуру для корней нечетного и четного деревьев, далее она рекурсивно выполняется для корней всех поддеревьев, которые, возможно, уже содержат узлы из нечетного и четного деревьев, поскольку ранее мог быть реализован случай
. Так как время манипулирования с любым ребром этих деревьев фиксированно, то общее время слияния деревьев составит .В результате описанных действий получится дерево
,в котором будут присутствовать поддеревья, которые прошли процедуру сличния, и которые ее избежали (т.е были перенесены в дерево без изменений).