Trie (префиксное дерево) в Python
Я не знаю, является ли это место, чтобы спросить об алгоритмах. Но посмотрим, получу ли я ответы ... :)
если что-то неясно, я очень рад прояснить вещи.
Я только что реализовал Бор в python. Тем не менее, один бит казался более сложным, чем должен (как тот, кто любит простоту). Возможно, у кого-то была аналогичная проблема?
моя цель состояла в том, чтобы минимизировать количество узлов, сохраняя самый большой общий префикс суб-дереве, в корне. Например, если бы у нас были слова stackoverflow, stackbase и stackbased, тогда дерево будет выглядеть так:
[s]tack
[o]verflow ______/ _______ [b]ase
___ [d]
обратите внимание, что все еще можно думать о ребрах, имеющих один символ (первый из дочернего узла).
найтизапрос-это простой в реализации. вставка не сложно, но несколько сложнее, чем я хочу.. :(
мой идея заключалась в том, чтобы вставить ключи один за другим (начиная с пустого trie), сначала ища ключ для вставки k (найти(k)), а затем перестановка/разделение узлов локально в том месте, где останавливается процедура поиска. Оказалось 4 случая: (Пусть k-ключ, который мы хотим вставить, и k ' - ключ узла, где поиск закончился)
- k идентичен k'
- k - "правильный" префикс k'
- k ' является a "правильный" префикс k
- k и k ' имеют некоторый общий префикс, но ни один из случаев (1), (2) или (3) не происходит.
Кажется, что каждый из случаев уникален и, следовательно, подразумевает различные модификации Trie. Но: это действительно так сложно? Я что-то упускаю? Есть ли лучший подход?
спасибо :)
5 ответов
на первый взгляд, похоже, что вы реализовали Патриция Три. Этот подход также называется сжатием пути в некоторых литературных источниках. Должны быть копии этой бумаги, которые не находятся за платежной стеной ACM, которая будет включать алгоритм вставки.
есть еще один метод сжатия, который вы можете посмотреть: уровень сжатия. Идея сжатия пути заключается в замене строк одиночных дочерних узлов одним суперузлом, который имеет отсчет" пропустить". Идея сжатия уровня заключается в замене полных или почти полных поддеревьев суперузлом с подсчетом "степени", который говорит, сколько цифр ключа декодирует узел. Существует также 3-й подход, называемый сжатием ширины, но я боюсь, что моя память подводит меня, и я не смог найти его описание с помощью быстрого гугления.
сжатие уровня может значительно сократить средний путь, но алгоритмы вставки и удаления становятся довольно сложными, поскольку им нужно управлять узлы trie аналогичны динамическим массивам. Для правильных наборов данных уровень сжатых деревьев может быть быстро. Из того, что я помню, они 2-й самый быстрый подход для хранения таблиц IP-маршрутизации, самый быстрый-это какой-то хэш-три.
Я не вижу ничего плохого в вашем подходе. Если вы ищете решение Спайка, возможно, действие, предпринятое в случае 4, действительно возможно для первых трех случаев, т. е. найти общий префикс k
и k'
и перестроить узел с учетом этого. Если случится так, что ключи были префиксами друг друга, результирующий trie все равно будет правильным, только реализация сделала немного больше работы, чем это было на самом деле. но опять же, без какого-либо кода смотреть на это трудно скажите, работает ли это в вашем случае.
несколько касательной, но если вы супер беспокоитесь о количестве узлов в вашем Trie, вы можете посмотреть на присоединение суффиксов слова тоже. Я бы взглянул на идею DAWG (Directed Acyclic Word Graph):http://en.wikipedia.org/wiki/Directed_acyclic_word_graph
недостатком этого является то, что они не очень динамичны, и их создание может быть трудным. Но, если словарь статичен, они могут быть супер компактный.
У меня есть вопрос относительно вашей реализации. Каков уровень детализации, на котором вы решили разделить строки, чтобы создать дерево префиксов. Вы можете разделить стек как s,t,a,c,k или st,ta,ac, ck и многие другие ngrams. Большинство реализаций дерева префиксов учитывают алфавит для языка, на основе этого алфавита вы делаете разбиение.
Если вы строили реализацию дерева префиксов для python, то ваши алфавиты будут такими, как def, : , если , то... и т. д.
выбор правильного алфавита имеет огромное значение для создания эффективных префиксных деревьев. Что касается ваших ответов, вы можете искать пакеты PERL на CPAN, которые делают самые длинные общие вычисления подстроки с помощью trie. Возможно, Вам повезет, поскольку большая часть их реализации довольно надежна.
посмотрите на: Judy-массивы и интерфейс python в http://www.dalkescientific.com/Python/PyJudy.html