我已经看到很多代码要解决这个问题,但是我无法理解为什么他们使用矩阵来表示两个单词之间的距离。有人可以向我解释一下吗?
以下是我找到的示例代码:
public static int minDistance(String word1, String word2)
{
int l1 = word1.length(), l2 = word2.length();
int[][] d = new int[l1 + 1][l2 + 1];
// the edit distance between an empty string and the prefixes of
// word2
for (int i = 0; i < l2 + 1; i++) {
d[0][i] = i;
}
// the edit distance between an empty string and the prefixes of
// word1
for (int j = 0; j < l1 + 1; j++) {
d[j][0] = j;
}
for (int i = 1; i < l1 + 1; i++) {
for (int j = 1; j < l2 + 1; j++) {
if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
d[i][j] = d[i - 1][j - 1];
} else {
d[i][j] = min(1 + d[i][j - 1], 1 + d[i - 1][j],
1 + d[i - 1][j - 1]); // min of insertion,
// deletion, replacement
}
}
}
return d[l1][l2];
}
答案 0 :(得分:5)
您的代码正在使用Levenshtein distance计算dynamic programming。
数组d
最终将包含各种子问题的解决方案,其中d[i][j]
是第一个单词的第一个i
个字母与第一个单词j
之间的距离第二个字母。 d[i][j]
与条目d[i-1][j]
,d[i][j-1]
和d[i-1][j-1]
之间存在关联。该算法以这样的方式计算表的条目,即已经计算了所需的子问题(这是动态编程部分)。
答案 1 :(得分:4)
矩阵包含[最后] word1
的所有前缀与word2
的所有前缀之间的编辑距离。
d[i][j] = edit distance between word1[0..(i-1)] and word2[0..(j-1)]
您对d[l1][l2]
感兴趣。通常,要计算d[i][j]
,您需要查看三个较小的邻居d[i-1][j]
,d[i-1][j-1]
和d[i][j-1]
。因此,d[i][j]
传递性地要求所有条目中至少有一个坐标小于i
resp j
(而另一个坐标不大)。例外情况是两个字符word1[i-1]
和word2[j-1]
相等,在这种情况下,您只需要对角线较小的邻居。
如果您首先使用-1
填充矩阵以指示尚未评估前缀之间的相应编辑距离,并使用所需d[l1][l2]
的缓存值递归计算d[i][j]
如果它已经被计算,递归地计算并且如果不是那么存储它的值,则矩阵的一些区域可以保持不变。如果存在多对相等字符,则可能是大区域[如果两个单词相等则仅评估对角线],如果有少量相等字符对,则只有小区域。
在一般情况下,计算d[l1][l2]
需要大部分矩阵,因此使用简单算法完全计算矩阵比仅重复和计算实际需要的值更快。
如果您不存储较短前缀的值,因为它们是传递上计算d[i][j]
所需的值,因此必须从d[i-a][j-b]
到达d[i][j]
的每一种方式重新计算它们}。由于d[i-a][j-b]
可以从d[i][j]
以多种方式到达min{l1, l2} + 1
,因此会导致重新计算很多次,从而导致算法效率极低。
由于每行的计算只使用前一行,你可以只使用两个长度为{{1}}的数组来节省一些内存,但除非单词真的很长,否则它没有太大区别,并且完整数组的代码更简单。
答案 2 :(得分:3)
代码可能很难理解,但这里有一些提示:
编辑两个字符串中任意一对字符之间的距离至少是在它们之前比较的所有字符对的编辑距离。例如,当您在比较 c 和 e 的阶段比较两个字符串 abc 和 ade 时,您确定编辑两个字符串的距离至少是到目前为止找到的最小编辑距离(在这种情况下为1)
如果比较的两个字符不相等,则编辑距离将增加1,表示替换。因此,如果您在比较之前知道字符串的编辑距离,则可以根据字符是否相等来添加1。
有这两个事实,
位置[i,j]是考虑的编辑距离
如果第i行元素不存在(表示插入成本),位置[i-1,j]将是字符串的总编辑距离
如果删除了第j个列元素,position [i,j-1]将是到目前为止字符串的总编辑距离(表示删除成本)
位置[i-i,j-1]将是迄今为所有先前元素计算的最小编辑距离
然后通过采用所有三种可能性中的最小值并添加当前决策来计算位置[i,j]。