如何有效地使用Levenshtein算法进行文本自动完成

时间:2015-06-01 07:40:27

标签: ios algorithm levenshtein-distance

我正在使用Levenshtein距离算法来过滤一些文本,以便为文本字段自动完成(以及前5个最佳结果)确定最佳匹配结果。

目前,我有一个字符串数组,并将算法应用于每个字符串,以尝试确定它与用户键入的文本的匹配程度。问题是我不太清楚如何解释算法输出的值,以便按预期有效地对结果进行排序。

例如:(文字类型=“ nvmb ”)

  1. 结果:“游戏”; levenshtein距离= 3(最佳匹配)
  2. 结果:“为明星编号”; levenshtein距离= 13(第二好的比赛)
  3. 这在技术上是有道理的;第二个结果需要更多的“编辑”,因为它的长度。问题是第二个结果在逻辑上和视觉上比第一个结果更接近。这几乎就像我应该忽略任何比输入文本长度更长的字符。

    关于如何实现这一目标的任何想法?

2 个答案:

答案 0 :(得分:0)

如果间隙和不匹配成本都是1,则Levenshtein距离对应于两个序列的最佳global pairwise alignment中的单字符插入,删除和替换的数量。

Needleman-Wunsch DP algorithm除了得分之外还会找到这样的对齐(它与用于计算Levenshtein距离的DP算法基本相同,但可以选择权重间隙,以及任何给定的不匹配一对字符,任意)。但是有一些更一般的对齐模型可以减少对开始或结束时的间隙的惩罚(并减少对连续的间隙块的处罚,这在这里也可能有用,尽管它没有直接回答这个问题)。在一个极端情况下,你有局部对齐,这是你在末端的差距根本不支付任何罚款的地方 - 这是由Smith-Waterman DP algorithm计算的。我认为你想要的是介于两者之间:你想在查询和测试字符串的开头,以及最后的测试字符串中的间隙,而不是最后的查询字符串中的间隙处罚间隙。这样,追踪不匹配就没有任何成本,而且成本看起来像是:

Query:    nvmb
Costs:    0100000000000000      =  1 in total
Against:  number the stars

Query:    nvmb
Costs:    1101                  =  3 in total
Against:  game

Query:    number the stars
Costs:    0100111111111111      = 13 in total
Against:  nvmb

Query:       ber     star
Costs:    1110001111100000      =  8 in total
Against:  number the stars

Query:    some numbor
Costs:    111110000100000000000 =  6 in total
Against:       number the stars

(实际上,您可能希望为尾随不匹配提供一个小的非零惩罚,因此完全匹配始终优先于仅前缀匹配。)

算法

假设查询字符串A的长度为n,而您要测试的字符串B的长度为m。设d [i] [j]为(i,j)处的DP表值 - 即A的长度为i的前缀与长度为j的前缀为B的最佳对齐的代价。如果你去了对于尾随不匹配的零惩罚,您只需要以非常简单的方式修改NW算法:您只需要像以前一样计算并返回DP表值,并且找到任何d [n] [j]的最小值,0 <= j <= m。这对应于查询字符串与测试字符串的任何前缀的最佳匹配。

答案 1 :(得分:0)

Levenshtein距离本身有助于纠正查询,而非自动完成。

我可以提出替代解决方案:

首先,将字符串存储在前缀树而不是数组中,因此您无需分析所有字符串。

其次,给定用户输入枚举与其具有固定距离的字符串,并建议任何完成。

您的示例:文字类型=“ nvmb

  1. 距离为0,没有完成
  2. 枚举距离为1的字符串
  3. 只有“麻木”会有一些完成
  4. 另一个例子:Text typed =“ gamb

    1. 对于距离0,您只有一个完成,“赌博”,首先提出建议,并继续获得4个
    2. 对于距离1,您将获得“游戏”以及一些完成
    3. 当然,这种方法有时会提供5个以上的结果,但您可以按照其他标准对其进行排序,而不是取决于当前的查询。

      我认为它更有效率,因为通常你可以限制距离最多为2,即检查1000 * n前缀的顺序,其中n是输入的长度,大多数时候小于存储的字符串的数量。