我目前正在实现一个基数树/帕特里夏特里(无论你想怎么称呼它)。我想用它在功能严重不足的硬件上的字典中进行前缀搜索。它应该或多或少像自动完成一样工作,即。e.显示与键入的前缀匹配的单词列表。

我的实现是基于 关于这篇文章, ,但其中的代码不包括前缀搜索,尽管作者说:

[...] 假设您想要枚举所有具有公共前缀“AB”的键的节点。您可以从该根开始执行深度优先搜索,并在遇到后边缘时停止。

但我不明白这应该如何运作。例如,如果我从这些单词构建一个基数树:

疾病
假想
想像力
想象
模仿
即时
立即地
巨大

对于前缀“i”和“in”,我将获得完全相同的“最佳匹配”,因此对我来说,仅通过从最佳匹配遍历树来收集所有匹配的单词似乎很困难。

此外,还有一个 Java中基数树的实现 已实现前缀搜索 RadixTreeImpl.java. 。该代码显式检查所有节点(从某个节点开始)是否有前缀匹配 - 它实际上比较字节。

谁能指出我在基数树上实现前缀搜索的详细描述?Java实现中使用的算法是唯一的方法吗?

有帮助吗?

解决方案

想想你的trie编码。在每个节点上,你已经道路,会导致你到这一点,所以在你的榜样,开始在Λ(这是一个首都Lambda,这是希腊字体样的烂)根节点对应一个空串。Λ有儿童对于每一个字母使用,所以在你的数据集,你有一个分支,对于"i"。

  • Λ
  • Λ→"我"

在"我"节点,还有两个孩子,一个"m"和一个"n"。下一个字母是"n",所以你拿去,

  • Λ→"我"→"n"

而由于只有开头的单词"i","n"在你的数据集 "在"没有儿童从"n"。那是一个匹配。

现在,让我们说的数据集,而不是具有"中"、已经"infindibulum".(什么SF我引用的是左作为行使。) 你仍然可以得到的"n"节点相同的方式,但随后如果下一封信,你得到的是"q",你知道这个词没有出现在你的数据集,因为没有"q"的分支。在这一点上,你说"好吧,没有匹配的。" (也许你然后开始加入这个词,也许不是,这取决于应用程序。)

但是,如果下一个字母是"f",你可以继续下去。你可以短路,有一点工艺品,但:一旦你到达一个节点代表了一个独特的道路,你可以挂在 整串 关闭那个节点。当你得到这点,你知道,其余的字符串 必须 是"findibulum",所以你已经使用的前缀以配合整串,并返回。

你如何使用?在很多非UNIX command口译员,像老VAX DCL,可以使用的任何独特的前缀的一个命令。因此,相当于 ls(1)DIRECTORY, 但没有任何其他命令开始与DIR,所以你可以的类型 DIR 这是不如做个字。如果你不记得正确的命令,则可能类型的'D'、和打(我认为)ESC;该DCL CLI会回你 所有 该命令,开始 D, 它可以搜索速度极快。

其他提示

原来的GNU扩展标准C ++的lib包括了Patricia特里结构实现。它是根据基于策略的数据结构的扩展中。请参见 http://gcc.gnu.org/onlinedocs/libstdc++/ext /pb_ds/trie_based_containers.html

另一种算法:保持简单愚蠢

只是让你的关键字排序列表。当你有一个前缀,找到二进制搜索中,前缀将设在列表中。所有可能的补全将开始该指数在这里找到,随时就位访问。

此算法将仅需要5%帕特里夏特里结构的代码的和将是易于维护,理解和更新。这几乎是一定的这一简单的列表搜索的效率会更高为好。

唯一的缺点是,如果你有类似的前缀长关键字庞大的数字,特里树可以节省一些存储,因为它并不需要保持完整的前缀每个条目。在实践中,如果你有不到几百万字,这不是储蓄,因为树的指针开销将占据主导地位。这是节约更多的像上百万个字符的搜索字符串DNA数据库的应用,而不是文本关键字。

另一种替代算法是 三元搜索树 (内存效率更高) https://github.com/varunpant/TernaryTree/tree/master/TernaryTree

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top