1632
правки
Изменения
Бор
,rollbackEdits.php mass rollback
'''Бор''' (англ. ''trie'', ''луч'', ''нагруженное дерево'') — {{---}} структура данных для хранения набора строк, представляющая из себя [[Дерево, эквивалентные определения | подвешенное дерево]] с символами на [[Основные определения теории графов | рёбрах]]. Строки получаются прохождением из корня по последовательной записью всех символов, хранящихся на [[Основные определения теории графов | рёбрамрёбрах]], записывая соответствующие им символы, до между корнем бора и терминальной вершинывершиной. Размер бора линейно
зависит от суммы длин всех строк, а поиск в бору занимает время, пропорциональное длине образца.
===Обозначения===
Введем следующие обозначения:
*<tex>\Sigma</tex> {{---}} используемый алфавит;*<tex>P = \{P_1,\ldots,P_k\} </tex> — {{---}} набор строкнад <tex>\Sigma</tex>, называемый словаремсловарём;*<tex>n = \sum_{i=1}^{k|P_i|}\limits |P_i|</tex>{{---}} сумма длин строк. Бор храним как деревонабор вершин, у каждой из которых есть метка, обозначающая, является ли вершина терминальной и указатели (рёбра) на другие вершины или на ''NULL''. '''struct''' vertex: '''vertex''' next[<tex>| \Sigma |</tex>] '''bool''' isTerminal
===Алгоритм===
Непосредственно построение:
*Начало.*'''Шаг 1.''' Начинаем с Создадим [[Дерево, эквивалентные определения | деревадерево]] из одной вершины (в нашем случае корня).*'''Шаг 2.''' Добавление элементов в дерево.**Добавляем шаблоны <tex>P_i</tex> один за другим. Следуем из корня по [[Основные определения теории графов | рёбрам]], отмеченным буквами из <tex>P_i</tex>, пока возможно.*'''Шаг 3.''' Определение дальнейших действий.
**Если <tex>P_i</tex> заканчивается в <tex>v</tex>, сохраняем идентификатор <tex>P_i</tex> (например, <tex>i</tex>) в <tex>v</tex> и отмечаем вершину <tex>v</tex> как терминальную.
**Если [[Основные определения теории графов | ребра]], отмеченного очередной буквой <tex>P_i</tex> нет, то создаем новые ребра новое ребро и вершины вершину для всех оставшихся символов символа строки <tex>P_i</tex>.*Конец.Это Построение занимает, очевидно, <tex>O(|P_1| + \ldots + |P_k|) = O(n)</tex> времени, так как поиск буквы, по которой нужно переходить, происходит за <tex>O(1)</tex>. Поскольку на каждую вершину приходится <tex>O(в вершине | \Sigma |)</tex> памяти, то использование памяти есть указатели на буквы<tex>O(n| \Sigma |)</tex>.
===Другие модификацииЦифровой бор===Бор позволяет решать задачу поиска подстроки в строке, если построить его на множестве суффиксов исходной строки. Такая модификация называется [[Суффиксный {{main|Сверхбыстрый цифровой бор | суффиксным бором]].}}
==Использование бора=====Поиск строки в бору===
{{Задача
|definition =
Требуется найти слово <tex>S</tex> в словаре.
}}
Если в какой-то момент [[Основные определения теории графов | ребра]], отмеченного нужным символом, не находится, то строки <tex>S</tex> в словаре нет.
Ясно, что это занимает <tex>O (|S|)</tex> времени. Таким образом, бор — это эффективный способ хранить словарь и искать в нем слова.
===Использование бора в качестве ассоциативного массива===Существует множество реализаций Благодаря тому, что бор позволяет решать задачу, описанную выше, он может выступать в качестве ассоциативного массива. Обычно, начиная от обычного массива (храним массив в отсортированном состояниикогда требуется такая структура, при добавлении элементато используют [[Дерево поиска, все элементы с большим значением сдвигаются) и заканчивая наивная реализация | двоичное дерево поиска]] или [[Хеш-таблица | хеш-таблицами таблицу]]. ====Достоинства====Бор объединяет некоторые преимущества этих структур данных и деревьями поиска. Ещё одну реализацию можно сделать используя бор или сжатый борпозволяет одновременно делать следующие операции, которые каждая из структур не может делать по отдельности.Начнём с очевидных минусов{| class="wikitable" style="width:10cm" border=1|+| || '''Бор''' || '''Дерево''' || '''Хеш-таблица'''|-|-align="center" bgcolor=#FFFFFF| ''Добавление элемента'' | align="center" style="background: #ddffdd;" | <tex>O(|S|)</tex>| align="center" style="background: #ffdddd;" |<tex>O(|S|\log k)</tex> | align="center" style="background: #ddffdd;" | <tex>O(|S|)</tex>|-align="center" bgcolor=#FFFFFF| ''Получение всех ключей в отсортированном порядке'' | align="center" style="background: #ddffdd;" | <tex>O(k)</tex>| align="center" style="background: #ddffdd;" | <tex>O(k)</tex> | align="center" style="background: #ffdddd;" | <tex>O(k\log k)</tex>|} ====Недостатки====Несмотря на данные достоинства у реализации ассоциативного массива в виде бора есть следующие недостатки:# Бор хранит строки или символы, а это значит, что у значения ключа будет ограничение на тип (строки, символы, либо числа, представленные как строки). Чтобы это исправить, научимся приводить любой тип данных к строке. Тогда сможем хранить любой вид данных в качестве ключа.# Если реализовывать ассоциативный массив на обычном боре, а ключами будут являться строки, то будет использоваться слишком много памяти(возможен, например, вариант, а так же будет большая константа# Если когда у нас все строки будут являться префиксами друг другаслов нет пересечений по префиксу, то поиск и добавление могут занимать тогда бор будет использовать <tex> O(n| \Sigma |)</tex> действий в худшем случае (например хранятся слова <tex>"a", "aa", "aaa", "aaaa", ...</tex>памяти), где <tex>n</tex> - количество словПлюсы:# Достаточно простая реализация.# Операции добавления имеют меньшую константу (из-за отсутствия всевозможных операций балансировки), чем у двоичных деревьев поиска, поэтому в среднем данная реализация может работать быстрее.# Сортировка элементов гарантируется уже самим построением бора.
==См. также==
* [[Сжатое суффиксное дерево]]
* [[Алгоритм Ахо-Корасик]]
== Источники информации ==