繁体   English   中英

Python中的Trie(前缀树)

[英]Trie (Prefix Tree) in Python

我不知道这是否是询问算法的地方。 但是,让我们看看我是否得到任何答案...... :)

如果有什么不清楚我很乐意澄清事情。

我刚刚在python中实现了一个Trie 然而,有一点似乎比它应该更复杂(作为一个喜欢简单的人)。 也许有人遇到过类似的问题?

我的目标是通过在其根中存储子trie的最大公共前缀来最小化节点数。 例如,如果我们有stackoverflowstackbasestackbased这两个词,那么树看起来像这样:

              [s]tack
[o]verflow ______/ \_______ [b]ase
                                  \___ [d]

注意,人们仍然可以想到边缘具有一个字符(子节点的第一个)。

查找 -query很容易实现。 插入并不难,但比我想要的更复杂.. :(

我的想法是一个接一个地插入密钥(从一个空的trie开始),首先搜索要插入的密钥k( Find (k)),然后在本地重新排列/拆分节点查找程序停止。 结果是4种情况:(设k是我们要插入的键,k'是节点的关键,搜索结束)

  1. k与k'相同
  2. k是k'的“正确”前缀
  3. k'是k的“正确”前缀
  4. k和k'共享一些共同的前缀,但没有一种情况发生(1),(2)或(3)。

似乎每个案例都是独特的,因此意味着对Trie的不同修改。 但是:真的那么复杂吗? 我错过了什么吗? 有更好的方法吗?

谢谢 :)

乍一看,听起来你已经实现了Patricia Trie 在一些文献中,这种方法也称为路径压缩。 应该有不在ACM付费专区后面的那篇论文的副本,其中将包括插入算法。

您还可以查看另一种压缩方法:级别压缩。 路径压缩背后的想法是用一个具有“跳过”计数的超级节点替换单个子节点的字符串。 级别压缩背后的想法是用超级节点替换完整或接近完整的子树,其中“度”计数表示节点解码的密钥的位数。 还有一种称为宽度压缩的第三种方法,但我担心我的记忆失败了,我无法通过快速谷歌搜索找到它的描述。

级别压缩可以显着缩短平均路径,但插入和删除算法变得非常复杂,因为它们需要像动态数组一样管理trie节点。 对于正确的数据集,级别压缩树可以很快 根据我的记忆,它们是存储IP路由表的第二快方法,最快的是某种哈希特里。

我认为你的方法没有任何问题。 如果你正在寻找尖峰解决方案,也许在案例4中采取的行动对于前三种情况实际上是可行的,IE找到kk'的公共前缀并重建节点时考虑到这一点。 如果碰巧键是彼此的前缀,那么生成的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,:,if,else等等

选择正确的字母表会对构建高效的前缀树产生巨大的影响。 至于你的答案,你可以在CPAN上寻找使用trie进行最长公共子串计算的PERL包。 你可能会有一些运气,因为他们的大多数实现非常强大。

请看:Judy-arrays和http://www.dalkescientific.com/Python/PyJudy.html上的python接口

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM