Поиск префикса по основному дереву / Patricia Trie - PullRequest
5 голосов
/ 27 апреля 2009

В настоящее время я использую основание дерева / Патрисии (как вы хотите это называть). Я хочу использовать его для поиска префиксов в словаре на жестком оборудовании. Он должен работать более или менее как автозаполнение, т.е. е. показывает список слов, которым соответствует набранный префикс.

Моя реализация основана на на этой статье , но код в ней не включает поиск префиксов, хотя автор говорит:

[...] Допустим, вы хотите перечислить все узлы, которые имеют ключи с общим префиксом «AB». Вы можете выполнить поиск в глубину, начиная с этого корня и останавливаясь всякий раз, когда вы сталкиваетесь с задними краями.

Но я не понимаю, как это должно работать. Например, если я построю основополагающее дерево из этих слов:

болезнь
мнимая
воображение
представьте
имитация
немедленный
немедленно
огромна
в

Я получу точно такое же "наилучшее совпадение" для префиксов "i" и "in", что мне будет сложно собрать все подходящие слова, просто пройдя по дереву из этого наилучшего совпадения.

Кроме того, в Java есть реализация radix tree, в которой реализован поиск префиксов в RadixTreeImpl.java . Этот код явно проверяет все узлы (начиная с определенного узла) на соответствие префикса - он фактически сравнивает байты.

Может ли кто-нибудь указать мне подробное описание реализации поиска по префиксу для радикальных деревьев? Является ли алгоритм, используемый в реализации Java, единственным способом сделать это?

Ответы [ 4 ]

8 голосов
/ 27 апреля 2009

Подумайте о том, что кодирует ваш файл. В каждом узле у вас есть путь, который ведет вас к этому узлу, поэтому в вашем примере вы начинаете с & Lambda; (это заглавная лямбда, этот греческий шрифт вроде отстой) корневой узел, соответствующий пустой строке. & Lambda; имеет дочерние элементы для каждой используемой буквы, поэтому в вашем наборе данных у вас есть одна ветвь для «i».

  • & Lambda;
  • & Lambda; & rarr; "я"

В узле "i" есть два дочерних элемента, один для "m" и один для "n". Следующая буква "n", так что вы принимаете это,

  • & Lambda; & rarr; "я" & rarr; "п"

и поскольку единственное слово, которое начинается с "i", "n" в вашем наборе данных - это"in", дочерних элементов от "n" нет. Это совпадение.

Теперь, скажем, в наборе данных вместо "in" был "infindibulum". (На какой SF я ссылаюсь, оставляем в качестве упражнения.) Вы все равно доберетесь до узла «n» таким же образом, но если следующая буква, которую вы получите, это «q», вы знаете, что слово не появляется в вашем наборе данных вообще, потому что нет ветки "q". В этот момент вы говорите: «Хорошо, нет совпадений». (Может быть, вы начнете добавлять слово, а может и нет, в зависимости от приложения.)

Но если следующая буква "f", вы можете продолжать. Вы можете замкнуть это с небольшим ремеслом, однако: как только вы достигнете узла, который представляет уникальный путь, вы можете повесить целую строку на этом узле. Когда вы попадаете на этот узел, вы знаете, что остальная часть строки должна быть "findibulum", поэтому вы использовали префикс, чтобы сопоставить всю строку и вернуть ее.

Как ты это используешь? во многих интерпретаторах команд, отличных от UNIX, таких как старый DCL VAX, вы можете использовать любой уникальный префикс команды. Итак, эквивалент ls (1) был DIRECTORY, но никакая другая команда не начиналась с DIR, так что вы могли бы набрать DIR, и это было так же хорошо, как и целое слово. Если вы не можете вспомнить правильную команду, вы можете просто набрать 'D' и нажать (я думаю) ESC; Интерфейс командной строки DCL вернет вам все команды, которые начинаются с D, которые он может найти чрезвычайно быстро.

3 голосов
/ 02 марта 2010

Оказывается, что расширения GNU для стандартного c ++ lib включают в себя реализацию Patricia trie. Он находится под расширением структур данных на основе политик. Смотри http://gcc.gnu.org/onlinedocs/libstdc++/ext/pb_ds/trie_based_containers.html

0 голосов
/ 19 июня 2013

Другим альтернативным алгоритмом является троичное дерево поиска (более эффективное использование памяти) https://github.com/varunpant/TernaryTree/tree/master/TernaryTree

0 голосов
/ 28 апреля 2009

Альтернативный алгоритм: Keep It Simple Stupid!

Просто составьте отсортированный список ваших ключевых слов. Если у вас есть префикс, бинарный поиск, чтобы найти, где этот префикс будет расположен в списке. Все ваши возможные дополнения будут найдены, начиная с этого индекса, и готовы к доступу на месте.

Для этого алгоритма потребуется всего 5% кода программы Patricia, и его будет легко поддерживать, понимать и обновлять. Почти наверняка этот простой поиск по списку также будет более эффективным.

Единственным недостатком является то, что если у вас огромное количество длинных ключевых слов с одинаковыми префиксами, три может сэкономить некоторое пространство, поскольку ему не нужно сохранять полный префикс для каждой записи. На практике, если у вас меньше нескольких миллионов слов, это не экономия, потому что указатель на верхнюю часть дерева будет доминировать. Эта экономия больше для таких приложений, как поиск в базах данных строк ДНК с миллионами символов, а не текстовых ключевых слов.

...