<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=178.178.22.166&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=178.178.22.166&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/178.178.22.166"/>
		<updated>2026-05-24T12:50:43Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B6%D0%B0%D1%82%D0%BE%D0%B5_%D1%81%D1%83%D1%84%D1%84%D0%B8%D0%BA%D1%81%D0%BD%D0%BE%D0%B5_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE&amp;diff=23136</id>
		<title>Сжатое суффиксное дерево</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B6%D0%B0%D1%82%D0%BE%D0%B5_%D1%81%D1%83%D1%84%D1%84%D0%B8%D0%BA%D1%81%D0%BD%D0%BE%D0%B5_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE&amp;diff=23136"/>
				<updated>2012-06-01T11:33:57Z</updated>
		
		<summary type="html">&lt;p&gt;178.178.22.166: /* Определение */ small fixup&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Суффиксный бор|Суффиксный бор]] {{---}} удобная структура данных для поиска подстроки в строке, но она занимает много места в памяти. Рассмотрим в боре все пути от &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; до  &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, в которых у каждой вершины только один сын. Такой путь можно сжать до ребра &amp;lt;tex&amp;gt;u v&amp;lt;/tex&amp;gt;, записав на нем все встречающиеся на пути символы, которые являются подстрокой исходной строки. Для хранения ее на ребре обычно используют индексы &amp;lt;tex&amp;gt;l, r&amp;lt;/tex&amp;gt; начала и конца. Получилось '''сжатое суффиксное дерево'''.&lt;br /&gt;
&lt;br /&gt;
==Определение==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Суффиксное дерево''' (сжатое суффиксное дерево) &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; (где  &amp;lt;tex&amp;gt;|s| = n&amp;lt;/tex&amp;gt;) {{---}} дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями, каждая внутренняя вершина которого имеет не меньше двух детей, а каждое ребро помечено непустой подстрокой строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Два ребра, выходящие из одной вершины, не могут иметь пометок, начинающихся с одного и того же символа. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Сжатое суффиксное дерево, как и бор, содержит все суффиксы строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;, причем каждый суффикс заканчивается точно в листе и нигде кроме него. [[Файл:Suffix_tree_3.png|thumb|right|Суффиксное дерево для строки &amp;lt;tex&amp;gt;xabxa&amp;lt;/tex&amp;gt; с защитным символом]] &lt;br /&gt;
Рассмотрим дерево для строки &amp;lt;tex&amp;gt;xabxa&amp;lt;/tex&amp;gt;. У него суффикс &amp;lt;tex&amp;gt;xa&amp;lt;/tex&amp;gt; является префиксом суффикса &amp;lt;tex&amp;gt;xabxa&amp;lt;/tex&amp;gt;, значит, этот суффикс не закачивается в листе. Для решения проблемы в конце строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; добавляют символ, не входящий в исходный алфавит: '''''защитный''''' символ. Как правило, это &amp;lt;tex&amp;gt;\$&amp;lt;/tex&amp;gt;. Любой суффикс строки с защитным символом действительно заканчивается в листе и только в листе.&lt;br /&gt;
&lt;br /&gt;
Далее &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; - длина строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; с защитным символом.&lt;br /&gt;
&lt;br /&gt;
==Количество вершин==&lt;br /&gt;
По определению, в суффиксном дереве содержится &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьев. Рассмотрим количество внутренних вершин такого дерева.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Количество внутренних вершин дерева, каждая из которых имеет не менее двух детей, меньше количества листьев.&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем лемму индукцией по количеству листьев &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''База'''&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;tex&amp;gt;n = 2&amp;lt;/tex&amp;gt; в дереве одна внутренняя вершина - верно.&lt;br /&gt;
&lt;br /&gt;
'''Переход''' &amp;lt;tex&amp;gt;n \rightarrow n + 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Возьмем вершину в дереве с &amp;lt;tex&amp;gt;n + 1&amp;lt;/tex&amp;gt; листами, у которой два ребенка - листья. Рассмотрим возможные случаи:&lt;br /&gt;
&lt;br /&gt;
1) У нее более двух детей. Тогда отрежем от нее лист. Получим дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями, причем в нем количество внутренних вершин такое же, как в исходном дереве. Но у полученного дерева по индукционному предположению менее &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; внутренних вершин, значит, для исходного дерева лемма верна.&lt;br /&gt;
&lt;br /&gt;
2) У нее ровно два ребенка. Отрежем их, получим дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями, количество внутренних вершин которого на &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; меньше, чем в исходном дереве. Тогда по индукционному предположению у него менее &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; внутренних вершин, значит, в исходном дереве их меньше &amp;lt;tex&amp;gt;n + 1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Занимаемая память==&lt;br /&gt;
Представим дерево как массив &amp;lt;tex&amp;gt;[|V|*|\Sigma|]&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;|V|&amp;lt;/tex&amp;gt; {{---}} количество вершин в дереве, &amp;lt;tex&amp;gt;|\Sigma|&amp;lt;/tex&amp;gt; - мощность алфавита. Для любого суффиксного дерева верна предыдущая лемма (у каждой вершины по определению не менее двух детей), значит, &amp;lt;tex&amp;gt;|V| = O(2*n)&amp;lt;/tex&amp;gt;. Каждая &amp;lt;tex&amp;gt;[i][j]&amp;lt;/tex&amp;gt; ячейка содержит информацию о том, в какую вершину ведет &amp;lt;tex&amp;gt;i-&amp;lt;/tex&amp;gt;ое ребро по &amp;lt;tex&amp;gt;j-&amp;lt;/tex&amp;gt;ому символу и индексы &amp;lt;tex&amp;gt;l, r&amp;lt;/tex&amp;gt;. Итак, дерево занимает &amp;lt;tex&amp;gt;O(n*|\Sigma|)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
&lt;br /&gt;
==Построение суффиксного дерева==&lt;br /&gt;
Рассмотрим наивный алгоритм построения суффиксного дерева:&lt;br /&gt;
 '''for''' &amp;lt;tex&amp;gt; i \leftarrow 0 &amp;lt;/tex&amp;gt; '''to''' &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; '''do''' //для каждого символа строки&lt;br /&gt;
     insert(&amp;lt;tex&amp;gt;i, n&amp;lt;/tex&amp;gt;) //добавляем суффикс, начинающийся с него&lt;br /&gt;
&lt;br /&gt;
 insert(l,r)&lt;br /&gt;
     &amp;lt;tex&amp;gt; cur \leftarrow root &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''while''' (&amp;lt;tex&amp;gt; i &amp;lt; r &amp;lt;/tex&amp;gt;)&lt;br /&gt;
          '''if''' &amp;lt;tex&amp;gt; go[cur][s[i]].v = 0 &amp;lt;/tex&amp;gt; //если мы не можем пойти из вершины по символу &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;&lt;br /&gt;
               create_vertex(&amp;lt;tex&amp;gt;cur, l, r&amp;lt;/tex&amp;gt;) //создаем новую вершину &lt;br /&gt;
          '''else'''&lt;br /&gt;
               &amp;lt;tex&amp;gt;start \leftarrow go[cur][s[i]].l &amp;lt;/tex&amp;gt;&lt;br /&gt;
               &amp;lt;tex&amp;gt;finish \leftarrow go[cur][s[i]].r &amp;lt;/tex&amp;gt;&lt;br /&gt;
               '''for''' &amp;lt;tex&amp;gt; j = start &amp;lt;/tex&amp;gt; '''to''' &amp;lt;tex&amp;gt; finish &amp;lt;/tex&amp;gt; //для каждого символа на ребре из текущей вершины&lt;br /&gt;
                    '''if''' &amp;lt;tex&amp;gt;s[i+j-start] &amp;lt;&amp;gt;s[j] &amp;lt;/tex&amp;gt; //если нашли не совпадающий символ&lt;br /&gt;
                         '''разбить ребро'''&lt;br /&gt;
                         '''break'''&lt;br /&gt;
               '''if''' '''ребро не разбивали'''&lt;br /&gt;
                    &amp;lt;tex&amp;gt;cur \leftarrow go[cur][s[i]].v &amp;lt;/tex&amp;gt; //переходим по ребру&lt;br /&gt;
                    &amp;lt;tex&amp;gt;i \leftarrow i + finish - start &amp;lt;/tex&amp;gt; //двигаемся по суффиксу на длину подстроки, записанной на ребре&lt;br /&gt;
&lt;br /&gt;
Этот алгоритм работает за время &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, однако [[Алгоритм Укконена| алгоритм Укконена]] позволяет построить сжатое суффиксное дерево за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Использование сжатого суффиксного дерева==&lt;br /&gt;
Суффиксное дерево позволяет за линейное время найти:&lt;br /&gt;
* Количество различных подстрок данной строки&lt;br /&gt;
* Наибольшую общую подстроку двух строк&lt;br /&gt;
* [[Суффиксный массив| Суффиксный массив]] и массив &amp;lt;tex&amp;gt;lcp&amp;lt;/tex&amp;gt; (longest common prefix) исходной строки&lt;br /&gt;
&lt;br /&gt;
==Источники==&lt;br /&gt;
*''Дэн Гасфилд'' — '''Строки, деревья и последовательности в алгоритмах: Информатика и вычислительная биология''' — СПб.: Невский Диалект; БХВ-Петербург, 2003. — 654 с: ил.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Словарные структуры данных ]]&lt;/div&gt;</summary>
		<author><name>178.178.22.166</name></author>	</entry>

	</feed>