如何修改Levenshteins编辑距离以将“相邻字母交换”计为1次编辑

时间:2010-10-29 20:05:21

标签: algorithm string levenshtein-distance

我正在玩Levenshteins Edit Distance algorithm,我想扩展它以计算换位 - 即相邻字母的交换 - 作为1次编辑。未修改的算法计算从另一个字符串到达​​某个字符串所需的插入,删除或替换。例如,从“KITTEN”到“SITTING”的编辑距离为3.以下是维基百科的解释:

  1. 小猫→坐着(用's'代替'k')
  2. sitten→sittin(用'i'代替'e')
  3. sittin→坐着(在结尾插入'g')。
  4. 按照相同的方法,从“CHIAR”到“CHAIR”的编辑距离为2:

    1. CHIAR→CHAR(删除'我')
    2. CHAR→CHAIR(插入'I')
    3. 我想把它算作“1编辑”,因为我只交换两个相邻的字母。我该怎么做呢?

3 个答案:

答案 0 :(得分:18)

您需要在维基百科的算法中再增加一个案例:

if s[i] = t[j] then 
  d[i, j] := d[i-1, j-1]
else if i > 0 and j > 0 and s[i] = t[j - 1] and s[i - 1] = t[j] then
  d[i, j] := minimum
             (
               d[i-2, j-2] + 1 // transpose
               d[i-1, j] + 1,  // deletion
               d[i, j-1] + 1,  // insertion
               d[i-1, j-1] + 1 // substitution
             )
else
  d[i, j] := minimum
             (
               d[i-1, j] + 1,  // deletion
               d[i, j-1] + 1,  // insertion
               d[i-1, j-1] + 1 // substitution
             )

答案 1 :(得分:1)

您必须修改更新动态编程表的方式。在原始算法中,人们考虑两个词的尾部(或头部)最多相差一个长度。更新是所有这些可能性中的最小值。

如果要修改算法,使两个相邻位置的变化计为1,则必须在最多相差2的尾部(或磁头)上计算上述最小值。您可以将其扩展到更大的社区,但复杂性将以该社区的大小呈指数级增长。

您可以进一步概括并分配取决于已删除,插入或替换的字符的成本,但您必须确保分配给成对编辑的成本低于两个单一编辑,否则两个单一编辑总是会赢。

让词语为w1和w2

dist(i,j) = min(
                dist(i-2,j-2) && w1(i-1,i) == w2(j-1,j) else
                dist(i-1,j-1) && w1(i) == w2(j) else
                dist(i,j-1)   + cost(w2(j)),
                dist(i-1,j)   + cost(w1(i)),
                dist(i-1,j-1) + cost(w1(i), w2(j)),
                dist(i, j-2)  + cost(w2(j-1,j)),
                dist(i-2, j)  + cost(w1(i-1,i)),
                dist(i-2,j-2) + cost(w1(i-1,i), w2(j-1,j))
                ) 

&&的意思是,只有满足条件时才应考虑这些行。

答案 2 :(得分:1)

其他答案正在实施最佳字符串对齐算法,而不是我认为你所描述的Damerau Levenshtein

我有一个OSA的java实现,其中有一些优化: https://gist.github.com/steveash/5426191