Изменения

Перейти к: навигация, поиск

Сжатое суффиксное дерево

3015 байт добавлено, 21:01, 21 мая 2015
Поиск строки максимальной длины, ветвящейся влево и вправо v 1.0
}}
[[Файл:RightMergingSS.png|thumb|right|Суффиксное дерево для строки <tex>aabcabd</tex>]]
Построим Первая часть алгоритма: построим Суффиксное дерево при помощи [[Алгоритм Укконена|Алгоритма Укконена]]. При создании ответвления будем увеличивать счётчик вершины, от которой идёт новый лист, на 1, если его пометка <tex>\ne</tex> <tex>\$</tex>. Таким образом, если у вершины счётчик <tex>></tex> 1, то подстрока, которую мы восстановим, идя вверх по дереву до корня, будет ветвящейся вправо (в примере для строки <tex>aabcabd</tex> это <tex>b</tex>, <tex>a</tex> и <tex>ab</tex>). Проделав аналогичную операцию Далее введём термины ''левый символ'' и ''вершина различная влево'', что бы найти строки, ветвящиеся влево.{{Определение|definition='''Левый символ''' для позиции <tex>i</tex> строки обратной исходной (<tex>reverseS</tex> - это символ <tex>S(abci-1)=cba</tex>), мы получим набор подстрок, ветвящихся влево (его элементы нужно развернуть обратно, чтобы получить исходные подстроки). Найдя пересечение двух множеств'''Левым символом''' листа <tex>L</tex> называется левый символ начала суффикса, мы получим набор строк, ветвящихся влево и вправо. Для корректности этого действия мы будем хранить номера первых символов подстроки, при пересечении будем учитывать не только содержание подстрок, но и их положение в исходной (лево- и право-ветвящаяся пара должна начинаться с одного и того же сивола). Максимальная строка последнего множества и будет ответомпредставляемого этим листом.}}{{ОпределениеТаким образом мы умеем искать строку максимальной длины|definition='''Вершина <tex>v</tex> различна влево''', ветвящуюся влево и вправо за если как минимум два листа в поддереве <tex>ST+O(N)v</tex>имеют различные ''левые символы''. По определению лист не может быть различным влево.}}
{{Теорема
|about=
алгоритм корректено строке, ветвящейся вправо и влево
|statement=
Докажем корректность алгоритма:#Предложенный алгоритм поиска строкиСтрока <tex>a</tex>, соответствующая пути к вершине <tex>v</tex>, является ветвящейся вправо корректен.#Предложенный алгоритм для перевёрнутой строки будет искать строку, ветвящуюся и влево.#Максимальный элемент пересечения предыдущих пунктов будет максимальной строкойтогда и только тогда, ветвящейся когда вершина <tex>v</tex> ''различна влево '' и вправосчётчик вершины <tex>></tex> 1.
|proof=
<tex>\Leftarrow</tex>
*Предположим, что <tex>v</tex> различна влево. Значит, что существуют подстроки <tex>cs</tex> и <tex>ds</tex>.
*Пусть за первой подстрокой следует символ <tex>p</tex>. Если за второй подстрокой следует символ, <tex>\ne p</tex>, то <tex>s</tex> - строка, ветвящаяся вправо и влево.
*Так как у <tex>v</tex> есть два различных ребёнка, которые начинаются с различных символов <tex>p,q \ne \$</tex>, строка является ветвящейся вправо.
 
<tex>\Rightarrow</tex>
*Пусть строка <tex>s</tex> является ветвящейся вправо и влево.
*Тогда существуют подстроки <tex>csa</tex> и <tex>dsb</tex>.
*В суффиксном дереве существует вершина <tex>v</tex> соответствующая строке <tex>s</tex> (так как есть как минимум два суффикса, начинающиеся со строки <tex>s</tex>).
*У вершины <tex>v</tex>, есть как минимум два ребёнка, которые начинаются с символов <tex>a</tex> и <tex>b</tex> <tex>\Rightarrow</tex> счётчик вершины <tex>></tex> 2.
*Так же у вершины <tex>v</tex>, есть как минимум два ребёнка, у которых ''левый символ'' <tex>c</tex> и <tex>d</tex>, значит вершина <tex>v</tex> ''различна влево'' по определению.
}}
 
Будем хранить в вершинах суффиксного дерева следующую информацию: левый символ или флаг, означающий, что вершина различна влево.
Вторая часть алгоритма начинает с листов суффиксного дерева, записывая для них левый символ. Затем мы обрабатываем вершины снизу вверх. При обработке вершины <tex>v</tex> проверяются её дети, если хотя бы один из них различен влево, то записываем, что вершина <tex>v</tex> различна влево.
Если никто из детей не различен влево, то проверяем их символы, привязанные к вершинам детей.
Если все символы равны <tex>x</tex>, то запишем в <tex>v x</tex>, иначе запишем в <tex>v</tex>, что она различна влево.
Так как время проверки детей <tex>v</tex> пропорционально числу детей, время работы всего алгоритма - <tex>O(n)</tex>.
 
Далее соберём все строки удовлетворяющие условию теоремы и найдём среди них максимальную (так же этот алгоритм можно использовать для нахождения количества строк, ветвящихся влево и вправо).
 
Таким образом мы умеем искать строку максимальной длины, ветвящуюся влево и вправо за <tex>ST+O(N)</tex>.
==См. также==
Анонимный участник

Навигация