什么algorithm在拼写检查器中给出build议?
实施拼写检查器时,通常使用哪种algorithm,并附带单词build议?
起初,我认为检查每个新input的单词(如果没有在字典中find的话)与字典中每个单词的Levenshtein距离相比 ,并返回最上面的结果是有意义的。 然而,这似乎是非常低效的,不得不反复评估整个字典。
这通常如何完成?
Peter Norvig有一篇很好的文章,说明如何实现一个拼写纠正器。 它基本上是一个蛮力的方法,尝试给定编辑距离的候选string。 ( 以下是一些提示,告诉您如何使用布隆filter和更快的候选哈希来提高拼写校正器的性能。
拼写检查器的要求较弱。 你只需要知道一个词不在词典里。 您可以使用Bloom Filter构build一个消耗较less内存的拼写检查器。 Jon Bentley在Programming Pearls的古代版本中使用了64kb的英文字典。
BK-Tree是另一种方法。 一篇不错的文章就在这里 。
Levenshstein距离并不完全是拼写检查器的正确编辑距离。 它只知道插入,删除和replace。 换位失踪,并产生2换1个字符(这是1删除和1插入)。 Damerau-Levenshtein距离是正确的编辑距离。
生成我已经成功使用但从未在任何地方描述的build议的方法是使用“坏”散列函数预先计算build议(在构build字典时)。
我们的想法是查看人们拼写错误的types,并devise散列函数,将错误的拼写分配给正确的拼写。
例如,一个常见的错误是使用错误的元音,如definate而不是确定的 。 所以你devise一个散列函数,把所有的元音当作同一个字母。 一个简单的方法是首先“正常化”input字,然后通过一个正则散列函数来归一化结果。 在这个例子中,标准化函数可能会删除所有元音,所以definite
变成dfnt
。 然后用典型的散列函数对“规格化”的字进行散列。
使用这个特殊的散列函数将所有的字典单词插入辅助索引(散列表)。 由于散列函数是“坏”的,这个表中的桶会有很长的冲突列表,但是这些冲突列表实质上是预先计算的build议。
现在,当您发现拼写错误的单词时,请查找拼写错误映射到辅助索引中的存储桶的冲突列表。 塔达:你有一个build议列表! 所有你需要做的就是排名上的话。
在实践中,你需要一些辅助索引和其他散列函数来处理其他types的错误,如转置字母,单/双字母,甚至是一个简单的类似Soundex的语音拼写错误。 在实践中,我发现单纯的发音很长,基本上已经过时了一些旨在发现微不足道的错别字的发音。
所以现在你在每个辅助索引中查找拼写错误,并在sorting之前连接碰撞列表。
记住碰撞列表只包含字典中的单词。 通过尝试生成替代拼写的方法(如Peter Norvig文章中所述),您可以获得(数十万)您首先必须对字典进行筛选的候选人。 用预先计算的方法,你可能会有几百名候选人,而且你知道他们都拼写正确,所以你可以直接跳到排名。
更新 :我已经find了一个类似于这个FAROO分布式search的algorithm描述。 这仍然是一个编辑距离有限的search,但它是非常快的,因为预计算步骤就像我的“坏散列函数”的想法。 FAROO只是使用有限的散列函数的概念。
algorithm
- 以拼写错误的单词作为input。
- 将英文单词列表及其频率存储在文本文件中。
- 在三元search树中插入所有可用的英文单词(存储在文本文件中)以及它们的频率(测量单词在英语中的使用频率)。
- 现在遍历三元search树 –
- 对于在三元search树中遇到的每个单词,从错误拼写的单词计算Levensthein距离。
- 如果Levensthein距离<= 3,则将该字存储在优先级队列中。
- 如果两个单词具有相同的编辑距离,则频率更高的单词更为粗糙。 打印Priority Queue中的前10个项目。
优化
- 如果当前单词的input单词的子串的编辑距离大于3,则可以在当前节点的子树中选出单词。
你可以在我的博客上find这个algorithm的更详细的解释,以及我的github项目上的所有源代码。
您不需要知道字典中每个单词的确切编辑距离。 您可以在达到极限值后停止algorithm并排除单词。 这将为您节省大量的计算时间。
拼写检查器很容易实现,如在Unix拼写程序。 源代码是公开的。 纠正可能涉及,一种技术是做编辑,并再次检查这个新单词是否在字典中。 这些新的编辑可以分组并显示给用户。
Unix系统使用Mc IllRoy编写的程序。 另一种方法是使用Trie,这对于大文件很有用。
- 我的Trie实验
- Unix喜欢实验
由于使用了散列哈希algorithm,因此unix方法需要的空间非常less。