Бор — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Построение)
(Использование бора в качестве ассоциативного массива)
Строка 38: Строка 38:
  
 
==Использование бора в качестве ассоциативного массива==
 
==Использование бора в качестве ассоциативного массива==
Мы можем ввести для каждой вершины поле <tex>\mathtt{value} \</tex>. Например, мы имеем <tex>\mathtt{map}</tex><tex><</tex><tex>\mathtt{string}\ , \mathtt{type}\ </tex><tex>></tex>. Будем искать ключ, спускаясь по бору. Соответственно, если на какой-то вершине нет пометки, что вершина является концом слова, то объекта в <tex>\mathtt{map}</tex> нет. Если хотим добавить его, то ставим в вершину флаг конца слова и заносим значение.
+
Существует множество реализаций ассоциативного массива, начиная от обычного массива (храним массив в отсортированном состоянии, при добавлении элемента, все элементы с большим значением сдвигаются) и заканчивая хеш-таблицами и деревьями поиска. Ещё одну реализацию можно сделать используя бор или сжатый бор.
Работать такой алгоритм будет за <tex>O(k)</tex>, где <tex>k</tex> {{---}} максимальная длина слова.
+
Начнём с очевидных минусов:
 +
# Бор хранит строки или символы, а это значит, что у значения ключа будет ограничение на тип (строки, символы, либо числа, представленные как строки).
 +
# Если реализовывать ассоциативный массив на обычном боре, а ключами будут являться строки, то будет использоваться слишком много памяти, а так же будет большая константа
 +
# Если у нас все строки будут являться префиксами друг друга, то поиск и добавление могут занимать <tex> O(n)</tex> действий в худшем случае (например хранятся слова <tex>"a", "aa", "aaa", "aaaa", ...</tex>), где <tex>n</tex> - количество слов
 +
Плюсы:
 +
# Достаточно простая реализация.
 +
# Операции добавления имеют меньшую константу (из-за отсутствия всевозможных операций балансировки), чем у двоичных деревьев поиска, поэтому в среднем данная реализация может работать быстрее.
 +
# Сортировка элементов гарантируется уже самим построением бора.
  
 
==См. также==
 
==См. также==

Версия 20:21, 6 апреля 2016

Бор (англ. trie, луч, нагруженное дерево) — структура данных для хранения набора строк, представляющая из себя подвешенное дерево с символами на рёбрах. Строки получаются прохождением из корня по рёбрам, записывая соответствующие им символы, до терминальной вершины. Размер бора линейно зависит от суммы длин всех строк, а поиск в бору занимает время, пропорциональное длине образца.

Пример

Бор для набора образцов [math] \{ \textbf{he}, \textbf{she}, \textbf{his}, \textbf{hers}\} [/math]:
Бор.jpg

Построение

Пусть [math]P = \{P_1,...,P_k\} [/math] — набор строк, называемый словарем.

Пусть [math]n = \sum_{i=1}^{k|P_i|}\limits |P_i|[/math].

Непосредственно построение:

  1. Начинаем с дерева из одной вершины (корня).
  2. Добавляем шаблоны [math]P_i[/math] один за другим.
  3. Следуем из корня по рёбрам, отмеченным буквами из [math]P_i[/math], пока возможно.
  4. Если [math]P_i[/math] заканчивается в [math]v[/math], сохраняем идентификатор [math]P_i[/math] (например, [math]i[/math]) в [math]v[/math] и отмечаем вершину [math]v[/math] как терминальную.
  5. Если ребра, отмеченного очередной буквой [math]P_i[/math] нет, то создаем новые ребра и вершины для всех оставшихся символов [math]P_i[/math].

Это занимает, очевидно, [math]O(|P_1| + \ldots + |P_k|) = O(n)[/math] времени, так как поиск буквы, по которой нужно переходить, происходит за [math]O(1)[/math](в вершине есть указатели на буквы).

Поскольку на каждую вершину приходится [math]O(k)[/math] памяти, то использование памяти есть [math]O(nk)[/math].

Бор позволяет решать задачу поиска подстроки в строке, если построить его на множестве суффиксов исходной строки.[1]

Существует еще одна модификация бора, называющаяся сжатый бор, отличающаяся от бора следующим улучшением: если у некоторой вершины исходящая степень равна 1, то эту вершину, ребро, входящее в нее, и ребро, исходящее из нее, можно объединить в одно ребро с более чем одним символом.

Поиск строки в бору

Задача:
Требуется найти слово в словаре.

Начинаем в корне, идем по рёбрам, отмеченным символами [math]S[/math], пока возможно. Если с последним символом [math]S[/math] мы приходим в вершину с сохраненным идентификатором, то [math]S[/math] — слово из словаря. Если в какой-то момент ребра, отмеченного нужным символом, не находится, то строки [math]S[/math] в словаре нет. Ясно, что это занимает [math]O (|S|)[/math] времени. Таким образом, бор — это эффективный способ хранить словарь и искать в нем слова.

Использование бора в качестве ассоциативного массива

Существует множество реализаций ассоциативного массива, начиная от обычного массива (храним массив в отсортированном состоянии, при добавлении элемента, все элементы с большим значением сдвигаются) и заканчивая хеш-таблицами и деревьями поиска. Ещё одну реализацию можно сделать используя бор или сжатый бор. Начнём с очевидных минусов:

  1. Бор хранит строки или символы, а это значит, что у значения ключа будет ограничение на тип (строки, символы, либо числа, представленные как строки).
  2. Если реализовывать ассоциативный массив на обычном боре, а ключами будут являться строки, то будет использоваться слишком много памяти, а так же будет большая константа
  3. Если у нас все строки будут являться префиксами друг друга, то поиск и добавление могут занимать [math] O(n)[/math] действий в худшем случае (например хранятся слова [math]"a", "aa", "aaa", "aaaa", ...[/math]), где [math]n[/math] - количество слов

Плюсы:

  1. Достаточно простая реализация.
  2. Операции добавления имеют меньшую константу (из-за отсутствия всевозможных операций балансировки), чем у двоичных деревьев поиска, поэтому в среднем данная реализация может работать быстрее.
  3. Сортировка элементов гарантируется уже самим построением бора.

См. также


Источники информации

  • Томас Х. Кормен, Чарльз И. Лейзерсон, Рональд Л. Ривест, Клиффорд Штайн Алгоритмы: построение и анализ — 2-е изд. — М.: «Вильямс», 2007. — ISBN 5-8489-0857-4
  • Бор. Построение бора

Ссылки

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