【问题标题】:What is the best autocomplete/suggest algorithm,datastructure [C++/C]什么是最好的自动完成/建议算法,数据结构 [C++/C]
【发布时间】:2010-12-19 12:17:13
【问题描述】:

我们看到 Google、Firefox 的一些 AJAX 页面在用户键入字符时显示可能的项目列表。

谁能给出一个好的算法,实现自动完成的数据结构?

【问题讨论】:

    标签: c++ c algorithm search autocomplete


    【解决方案1】:

    对于大型数据集,后端的一个很好的候选者是三元搜索树。它们结合了两个方面的优点:二叉搜索树的低空间开销和数字搜索尝试的基于字符的时间效率。

    参见 Dobbs 博士杂志:http://www.ddj.com/windows/184410528

    目标是在用户输入时快速检索有限的结果集。让我们首先考虑搜索“计算机科学”,您可以从“计算机”或“科学”开始输入,但不能从“计算机”开始输入。因此,给定一个短语,生成以单词开头的子短语。现在对于每个短语,将它们输入 TST(三元搜索树)。 TST 中的每个节点都将表示到目前为止已键入的短语的前缀。我们将在该节点中存储该前缀的最佳 10 个(比如说)结果。如果一个节点的候选结果多于有限数量的结果(此处为 10 个),则应该有一个排名函数来解决两个结果之间的竞争。

    树可以每隔几个小时构建一次,具体取决于数据的动态性。如果数据是实时的,那么我想其他一些算法会提供更好的平衡。在这种情况下,绝对要求是对每次键入的击键都进行闪电般的快速检索结果,这非常好。

    如果涉及拼写更正的建议,将会出现更多的复杂情况。在这种情况下,还必须考虑编辑距离算法。

    对于像国家列表这样的小型数据集,Trie 的简单实现就可以了。如果您要在 Web 应用程序中实现这样的自动完成下拉菜单,则在您提供列表中的数据后,YUI3 的自动完成小部件将为您完成所有工作。如果您将 YUI3 仅用作大数据支持的自动完成的前端,请在 C++ 中制作基于 TST 的 Web 服务,然后使用自动完成小部件的脚本节点数据源从 Web 服务中获取数据,而不是简单的列表。

    【讨论】:

      【解决方案2】:

      trie 是一种数据结构,可用于快速查找与前缀匹配的单词。

      编辑:这是一个示例,展示如何使用一个来实现自动完成http://rmandvikar.blogspot.com/2008/10/trie-examples.html

      这是 3 个不同的auto-complete implementations 的比较(尽管它是在 Java 中而不是 C++ 中)。

      * In-Memory Trie
      * In-Memory Relational Database
      * Java Set
      

      在查找键时,trie 比 Set 实现要快一些。 trie 和 set 都比关系数据库解决方案快很多。

      Set 的设置成本低于 Trie 或 DB 解决方案。您必须决定是否经常构建新的“词集”,或者查找速度是否是更高的优先级。

      这些结果在 Java 中,您的里程可能会因 C++ 解决方案而异。

      【讨论】:

      • 有点相关的是 Google 的 Peter Norvig 对如何进行拼写更正的描述:norvig.com/spell-correct.html
      • 标准 Trie 非常占用内存,对于较大的集合,您想使用 Compacted Trie,从而大大减少内存占用。其他优化包括节点值的延迟初始化和子/值集的正确数据结构。不久前,我创建了一个 autocomplete library 能够处理非常大的数据集(10,000,000+)并有效地回答精确和近似搜索。
      【解决方案3】:

      Segment trees可用于高效实现auto complete

      【讨论】:

        【解决方案4】:

        如果您想建议最受欢迎的完成,“建议树”可能是一个不错的选择: Suggest Tree

        【讨论】:

          【解决方案5】:

          对于一个简单的解决方案:您生成一个具有最小编辑 (Levenshtein) 距离(1 或 2)的“候选人”,然后使用哈希容器(set对于一个简单的解决方案就足够了,然后使用 tr1 或 boost 中的 unordered_set

          示例: 你写了卡尔,你想要汽车。 arr 由 1 次删除生成。 arr 在您的 unordered_set 中吗?编号 crr 由 1 次删除生成。 crr 在您的 unordered_set 中吗?车号是1次删除生成的。 car 在你的 unordered_set 中吗?是的,你赢了。

          当然还有插入、删除、转置等……

          您发现生成候选者的算法确实是在浪费时间,尤其是当您的 unordered_set 非常少时。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-06-02
            • 2012-03-17
            • 2012-02-03
            • 1970-01-01
            • 2012-05-30
            • 2017-11-20
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多