我正在玩Levenshteins Edit Distance algorithm,我想扩展它以计算换位 - 即相邻字母的交换 - 作为1次编辑。未修改的算法计算从另一个字符串到达某个字符串所需的插入,删除或替换。例如,从“KITTEN”到“SITTING”的编辑距离为3.以下是维基百科的解释:
按照相同的方法,从“CHIAR”到“CHAIR”的编辑距离为2:
我想把它算作“1编辑”,因为我只交换两个相邻的字母。我该怎么做呢?
答案 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