【问题标题】:What is a good algorithm to traverse a Trie to check for spelling suggestions?什么是遍历 Trie 以检查拼写建议的好算法?
【发布时间】:2011-03-16 03:19:39
【问题描述】:

假设构建了字典单词的一般 Trie,那么在遍历过程中检查 4 种拼写错误(替换、删除、转置和插入)的最佳方法是什么?

一种方法是找出给定单词的 n 个编辑距离内的所有单词,然后在 Trie 中检查它们。这不是一个坏选择,但这里更好的直觉似乎是使用动态编程(或递归等效)方法来确定在遍历期间修改单词后的最佳子尝试。

欢迎任何想法!

PS,不胜感激实际输入,而不仅仅是答案中的链接。

【问题讨论】:

  • 对于那些看到“Trie”并认为它是“Tree”的拼写错误的人来说,考虑到上下文,这将是非常具有讽刺意味的。 en.wikipedia.org/wiki/Trie

标签: algorithm spell-checking dynamic-programming trie


【解决方案1】:

看看计算Levenshtein distance,它提供了一种动态规划解决方案来查找两个序列之间的距离。

【讨论】:

  • 感谢您的回答。我知道 Levenshtein - 我正在处理的问题是我不知道与哪个词进行比较。相反,我想做的是生成给定编辑距离内的单词列表..
【解决方案2】:

我认为您可以通过在树上进行简单的广度优先搜索来做到这一点:选择您要查找的错误数量的阈值,只需一次遍历要匹配的单词的字母,生成到目前为止达到的与前缀匹配的一组 (prefix, subtrie) 对,当您低于错误阈值时,添加到您的下一个子目标集:

  1. 此字符位置没有错误:在单词的下一个字符处添加 trie 的子目标
  2. 在此位置插入、删除或替换的字符:在此处找到适当的 trie,并增加错误计数;
  3. 不是一个额外的目标,但请注意,转座是插入或与较早的删除或插入相匹配的删除:如果此测试成立,则不要增加错误计数。

这似乎很幼稚:这是否有问题导致您想到动态编程?

【讨论】:

    【解决方案3】:

    假设单词中的每个连续字符都代表树中的一个级别,那么您需要检查每个字符的五种情况(匹配、删除、插入、替换和转置)。我假设换位是两个相邻的字符。

    您将需要一个函数 (CheckNode),它接受一个树节点和一个要检查的字符。它需要返回一组表示匹配的(子/孙子)节点。

    您将需要一个接受单词的函数 (CheckWord)。它依次对照一组节点检查每个字符。它将返回一组表示匹配单词的(叶)节点。

    这个想法是树中的每个级别(子级、孙级等)都匹配单词中字符的位置。如果您调用顶级树节点,级别 0,那么您将拥有级别 1、级别 2 等。

    显然对于一个没有错误的单词,字符位置和树中的级别是一一匹配的。

    对于删除,您需要跳过树中的一个级别。

    对于插入,您需要跳过单词中的一个字符。

    对于替换,您需要跳过一个级别和一个字符。

    对于换位,您需要(暂时)交换单词中的字符。

    【讨论】:

    • 除了将替换限制为相邻字符之外,这与我的答案有什么不同吗?
    • @Charles Stewart 我同意这仍然是广度优先搜索。但我不依赖错误计数,因为 Viksit 只需要拼写建议(叶节点)。我还提供了可能解决问题的程序的潜在结构的提示。
    【解决方案4】:

    前几天我实际上写了一些代码来做到这一点:

    https://bitbucket.org/teoryn/spell-checker/src/tip/spell_checker.py

    它基于 Peter Norvig (http://norvig.com/spell-correct.html) 的代码,但将字典存储在 trie 中,以便更快地查找给定编辑距离内的单词。

    该算法通过消耗输入单词中的字母,递归地在每个步骤中应用可能的编辑(或不进行编辑)。递归调用的参数说明可以进行多少次编辑。 trie 通过检查我们给定的前缀实际上可以到达哪些字母来帮助缩小搜索空间。例如,当插入一个字符时,我们只添加从当前节点可到达的字母,而不是添加字母表中的每个字母。不进行编辑相当于从 trie 中的当前节点沿输入单词的当前字母获取分支。如果该分支不存在,那么我们可以回溯并避免搜索可能无法找到真实单词的大空间。

    【讨论】:

    • +1 代码。我很惊讶代码中没有更多棘手的案例。
    • @ColonelPanic 抱歉,我修复了链接。
    猜你喜欢
    • 2011-01-18
    • 2013-04-15
    • 2011-05-11
    • 1970-01-01
    • 2010-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多