Сжатое суффиксное дерево — различия между версиями
Строка 1: | Строка 1: | ||
− | '''Суффиксное дерево''' (сжатое суффиксное дерево) <tex>T</tex> для строки <tex>s</tex> (где <tex>|s| = n</tex>) {{---}} ориентированное дерево с | + | [[Суффиксный бор|Суффиксный бор]] {{---}} удобная структура для поиска подстроки в строке, но занимающая много места в памяти. Рассмотрим все такие пути от <tex>u</tex> до <tex>v</tex> в суффиксном боре, в которых каждая вершина имеет только одного сына. Такие пути можно сжать до одного ребра <tex>u v</tex>, пометив его всеми встречающимися на пути символами. Получившееся дерево носит название '''сжатое суффиксное дерево'''. |
+ | |||
+ | ==Определение== | ||
+ | '''Суффиксное дерево''' (сжатое суффиксное дерево) <tex>T</tex> для строки <tex>s</tex> (где <tex>|s| = n</tex>) {{---}} ориентированное дерево, с ровно <tex>n</tex> листами, каждая внутренняя вершина которого, отличная от корня, имеет не меньше двух детей, а каждое ребро помечено непустой подстрокой строки <tex>s</tex> и символом, с которого начинается эта подстрока. Никакие два ребра, выходящие из одной и той же вершины, не могут иметь одинаковых символьных пометок. Суффиксное дерево содержит все суффиксы строки <tex>s</tex>: для каждого листа <tex>i</tex> конкатенация подстрок на ребрах пути от корня к листу <tex>i</tex> в точности составляет суффикс, который начинается в позиции <tex>i</tex>, то есть <tex>s[i..n]</tex>. | ||
==Существование сжатого суффиксного дерева== | ==Существование сжатого суффиксного дерева== | ||
[[Файл:Suffix_tree_3.png|thumb|right|Суффиксное дерево для строки <tex>xabxa</tex> с защитным символом]] | [[Файл:Suffix_tree_3.png|thumb|right|Суффиксное дерево для строки <tex>xabxa</tex> с защитным символом]] | ||
− | Определение суффиксного дерева не гарантирует, что такое дерево существует для любой строки <tex>s</tex>. Если один суффикс совпадает с префиксом другого суффикса, то построить суффиксное дерево, удовлетворяющее данному выше определению, невозможно, поскольку путь для первого суффикса не сможет закончиться в листе. Например, для строки <tex>xabxa</tex> суффикс <tex>xa</tex> является префиксом суффикса <tex>xabxa</tex>. Во избежание этого в конце строки <tex>s</tex> добавляется символ, не входящий в исходный алфавит. Такой символ называется '''''защитным'''''. Как правило, защитный символ обозначается <tex>\$</tex>. | + | Определение суффиксного дерева не гарантирует, что такое дерево существует для любой строки <tex>s</tex>. Если один суффикс совпадает с префиксом другого суффикса, то построить суффиксное дерево, удовлетворяющее данному выше определению, невозможно, поскольку путь для первого суффикса не сможет закончиться в листе. Например, для строки <tex>xabxa</tex> суффикс <tex>xa</tex> является префиксом суффикса <tex>xabxa</tex>. Во избежание этого в конце строки <tex>s</tex> добавляется символ, не входящий в исходный алфавит. Такой символ называется '''''защитным'''''. Как правило, защитный символ обозначается <tex>\$</tex>. Любой суффикс строки с защитным символом заканчивается в листе, т.к. этот символ не встречается в строке нигде, кроме позиции последнего символа. |
+ | |||
+ | ==Хранение суффиксного дерева== | ||
+ | Как уже было отмечено выше, каждое ребро дерева помечается подстрокой исходной строки <tex>s</tex>. Значит, можно для каждого ребра хранить не саму подстроку, а индексы начала и конца подстроки в исходной строке {{---}} <tex>l, r</tex>. Итак, с каждым ребром дерева ассоциируются две инцидентные ей вершины, символ, с которого начинается подстрока на ребре и два числа <tex>l, r</tex>. Представим его как массив <tex>[|V|*|\Sigma|]</tex>, где <tex>|V|</tex> {{---}} количество вершин в дереве. Каждая <tex>[i][j]</tex> ячейка массива содержит информацию о том, в какую вершину ведет <tex>i-ое</tex> ребро по <tex>j-ому</tex> символу, в какую вершину оно ведет и индексы <tex>l, r</tex> подстроки на ребре. | ||
− | == | + | ==Количество вершин== |
− | + | В сжатом суффиксном дереве содержится <tex>n</tex> листьев, т.к. каждый суффикс строки <tex>s</tex> заканчивается в листе. Рассмотрим теперь количество внутренних вершин такого дерева. | |
− | |||
{{Лемма | {{Лемма | ||
|statement= | |statement= | ||
Строка 21: | Строка 26: | ||
'''Переход''' <tex>n \rightarrow n + 1</tex> | '''Переход''' <tex>n \rightarrow n + 1</tex> | ||
− | Рассмотрим все вершины, у которых хотя бы один из детей - лист. | + | Рассмотрим все вершины в дереве для строки длины <tex>n + 1</tex>, у которых хотя бы один из детей - лист. |
− | Если среди них есть вершина, у которой более двух детей, отрежем от нее лист. Получим дерево с <tex>n</tex> листьями, удовлетворяющее условию леммы, в | + | Если среди них есть вершина, у которой более двух детей, отрежем от нее лист. Получим дерево с <tex>n</tex> листьями, удовлетворяющее условию леммы по индукционному предположению, причем в нем количество внутренних вершин равно количеству внутренних вершин в исходном дереве. Тогда у полученного дерева менее <tex>n</tex> внутренних вершин, значит в исходном дереве количество внутренних вершин так же меньше количества листьев. |
Иначе среди этих вершин есть вершина, у которой оба ребенка - листья. Отрежем оба этих листа, получим дерево с <tex>n</tex> листьями, удовлетворяющее условию леммы, количество внутренних вершин которого на <tex>1</tex> меньше количества внутренних вершин в исходном дереве. Тогда, по индукционному предположению, у полученного дерева менее <tex>n</tex> внутренних вершин, значит в исходном дереве количество внутренних вершин меньше <tex>n + 1</tex>. | Иначе среди этих вершин есть вершина, у которой оба ребенка - листья. Отрежем оба этих листа, получим дерево с <tex>n</tex> листьями, удовлетворяющее условию леммы, количество внутренних вершин которого на <tex>1</tex> меньше количества внутренних вершин в исходном дереве. Тогда, по индукционному предположению, у полученного дерева менее <tex>n</tex> внутренних вершин, значит в исходном дереве количество внутренних вершин меньше <tex>n + 1</tex>. | ||
}} | }} | ||
− | == | + | ==Занимаемая память== |
− | Так как суффиксное дерево удовлетворяет условиям леммы, то количество внутренних вершин в нем меньше количества листьев, поэтому для его хранения требуется <tex>O(n|\Sigma|)</tex> памяти. | + | Очевидно, суффиксное дерево в виде массива занимает <tex>O(|V||\Sigma|)</tex> памяти. Так как любое суффиксное дерево удовлетворяет условиям леммы, то количество внутренних вершин в нем меньше количества листьев, равного <tex>n</tex>, поэтому для его хранения требуется <tex>O(n|\Sigma|)</tex> памяти. |
+ | |||
+ | ==Построение суффиксного дерева== | ||
+ | Рассмотрим наивный алгоритм построения суффиксного дерева. | ||
+ | |||
+ | Этот алгоритм работает за время<tex>O(n^2)</tex>, однако существует [[Алгоритм Укконена| алгоритм Укконена]], позволяющий построить дерево за время<tex>O(n)</tex>. | ||
==Использование== | ==Использование== | ||
Строка 35: | Строка 45: | ||
* Количество различных подстрок данной строки | * Количество различных подстрок данной строки | ||
* Наибольшую общую подстроку двух строк | * Наибольшую общую подстроку двух строк | ||
− | * [[Суффиксный массив| Суффиксный массив]] и массив <tex>lcp</tex> (longest common prefix) | + | * [[Суффиксный массив| Суффиксный массив]] и массив <tex>lcp</tex> (longest common prefix) исходной строки |
==Источники== | ==Источники== | ||
''Дэн Гасфилд'' — '''Строки, деревья и последовательности в алгоритмах: Информатика и вычислительная биология''' — СПб.: Невский Диалект; БХВ-Петербург, 2003. — 654 с: ил. | ''Дэн Гасфилд'' — '''Строки, деревья и последовательности в алгоритмах: Информатика и вычислительная биология''' — СПб.: Невский Диалект; БХВ-Петербург, 2003. — 654 с: ил. |
Версия 16:27, 22 апреля 2012
Суффиксный бор — удобная структура для поиска подстроки в строке, но занимающая много места в памяти. Рассмотрим все такие пути от до в суффиксном боре, в которых каждая вершина имеет только одного сына. Такие пути можно сжать до одного ребра , пометив его всеми встречающимися на пути символами. Получившееся дерево носит название сжатое суффиксное дерево.
Содержание
Определение
Суффиксное дерево (сжатое суффиксное дерево)
для строки (где ) — ориентированное дерево, с ровно листами, каждая внутренняя вершина которого, отличная от корня, имеет не меньше двух детей, а каждое ребро помечено непустой подстрокой строки и символом, с которого начинается эта подстрока. Никакие два ребра, выходящие из одной и той же вершины, не могут иметь одинаковых символьных пометок. Суффиксное дерево содержит все суффиксы строки : для каждого листа конкатенация подстрок на ребрах пути от корня к листу в точности составляет суффикс, который начинается в позиции , то есть .Существование сжатого суффиксного дерева
Определение суффиксного дерева не гарантирует, что такое дерево существует для любой строки
. Если один суффикс совпадает с префиксом другого суффикса, то построить суффиксное дерево, удовлетворяющее данному выше определению, невозможно, поскольку путь для первого суффикса не сможет закончиться в листе. Например, для строки суффикс является префиксом суффикса . Во избежание этого в конце строки добавляется символ, не входящий в исходный алфавит. Такой символ называется защитным. Как правило, защитный символ обозначается . Любой суффикс строки с защитным символом заканчивается в листе, т.к. этот символ не встречается в строке нигде, кроме позиции последнего символа.Хранение суффиксного дерева
Как уже было отмечено выше, каждое ребро дерева помечается подстрокой исходной строки
. Значит, можно для каждого ребра хранить не саму подстроку, а индексы начала и конца подстроки в исходной строке — . Итак, с каждым ребром дерева ассоциируются две инцидентные ей вершины, символ, с которого начинается подстрока на ребре и два числа . Представим его как массив , где — количество вершин в дереве. Каждая ячейка массива содержит информацию о том, в какую вершину ведет ребро по символу, в какую вершину оно ведет и индексы подстроки на ребре.Количество вершин
В сжатом суффиксном дереве содержится
листьев, т.к. каждый суффикс строки заканчивается в листе. Рассмотрим теперь количество внутренних вершин такого дерева.Лемма: |
Количество внутренних вершин дерева, каждая из которых имеет не менее двух детей, меньше количества листьев. |
Доказательство: |
Докажем лемму индукцией по количеству листьев .База При в дереве одна внутренняя вершина - верно.Переход Рассмотрим все вершины в дереве для строки длины , у которых хотя бы один из детей - лист.Если среди них есть вершина, у которой более двух детей, отрежем от нее лист. Получим дерево с Иначе среди этих вершин есть вершина, у которой оба ребенка - листья. Отрежем оба этих листа, получим дерево с листьями, удовлетворяющее условию леммы по индукционному предположению, причем в нем количество внутренних вершин равно количеству внутренних вершин в исходном дереве. Тогда у полученного дерева менее внутренних вершин, значит в исходном дереве количество внутренних вершин так же меньше количества листьев. листьями, удовлетворяющее условию леммы, количество внутренних вершин которого на меньше количества внутренних вершин в исходном дереве. Тогда, по индукционному предположению, у полученного дерева менее внутренних вершин, значит в исходном дереве количество внутренних вершин меньше . |
Занимаемая память
Очевидно, суффиксное дерево в виде массива занимает
памяти. Так как любое суффиксное дерево удовлетворяет условиям леммы, то количество внутренних вершин в нем меньше количества листьев, равного , поэтому для его хранения требуется памяти.Построение суффиксного дерева
Рассмотрим наивный алгоритм построения суффиксного дерева.
Этот алгоритм работает за время алгоритм Укконена, позволяющий построить дерево за время .
, однако существуетИспользование
Суффиксное дерево позволяет за линейное время найти:
- Количество различных подстрок данной строки
- Наибольшую общую подстроку двух строк
- Суффиксный массив и массив (longest common prefix) исходной строки
Источники
Дэн Гасфилд — Строки, деревья и последовательности в алгоритмах: Информатика и вычислительная биология — СПб.: Невский Диалект; БХВ-Петербург, 2003. — 654 с: ил.