求解编辑距离的动态规划算法
Post on · 28 views · Edit it on Github编辑距离(Edit Distance)是一种用于比较两个字符串之间相似度的计算方法,其定义为:将字符串 X 转换成字符串 Y 所需要的字符操作的最少次数,这里的操作是指插入(Insert)、删除(Delete)或替换(Substitute)。
比如,字符串 vary 和 every 的编辑距离是 2,因为可以通过以下的两步操作进行转换:
- 在串首插入字符
e,得到evary - 将字符
a替换成e,得到every
编辑距离越小,表示两个字符串之间的相似度越大,所以常被用于单词的拼写检查或生物的 DNA 序列检测等问题上。
一、数学分析
对编辑距离的求解,需要用到动态规划的思想。即通过拆分,将对原问题的求解划分为对一系列相对简单的重叠子问题的求解,然后再合并这些子问题的解去一步步得到原问题的解。
设两个字符串分别为 X = X 1 ⋯ X i " role="presentation"> X=X1⋯Xi, Y = Y 1 ⋯ Y j " role="presentation"> Y=Y1⋯Yj,其编辑距离为 d i , j " role="presentation"> di,j。那么可知:
-
若在 d i , j − 1 " role="presentation"> di,j−1 个操作内,可以将 X 1 ⋯ X i " role="presentation"> X1⋯Xi 转换为 Y 1 ⋯ Y j − 1 " role="presentation"> Y1⋯Yj−1,那么必然可以在 d i , j − 1 + 1" role="presentation"> di,j−1+1 个操作内将 X 1 ⋯ X i " role="presentation"> X1⋯Xi 转换为 Y 1 ⋯ Y j " role="presentation"> Y1⋯Yj。这里的 + 1" role="presentation"> +1 操作表示将 Y j " role="presentation"> Yj 插入到 Y 1 ⋯ Y j − 1 " role="presentation"> Y1⋯Yj−1 中;
-
若在 d i − 1 , j " role="presentation"> di−1,j 个操作内,可以将 X = X 1 ⋯ X i " role="presentation"> X=X1⋯Xi 转换为 Y 1 ⋯ Y j " role="presentation"> Y1⋯Yj,那么必然可以在 d i − 1 , j + 1" role="presentation"> di−1,j+1 个操作内将 X 1 ⋯ X i " role="presentation"> X1⋯Xi 转换为 Y 1 ⋯ Y j " role="presentation"> Y1⋯Yj。这里的 + 1" role="presentation"> +1 操作表示把 X i " role="presentation"> Xi 从 X = X 1 ⋯ X i " role="presentation"> X=X1⋯Xi 中删除;
-
若在 d i − 1 , j − 1 " role="presentation"> di−1,j−1 个操作内,可以将 X = X 1 ⋯ X i " role="presentation"> X=X1⋯Xi 转换为 Y 1 ⋯ Y j − 1 " role="presentation"> Y1⋯Yj−1,那么:
- 如果 X i = Y j " role="presentation"> Xi=Yj,则必然可在 d i − 1 , j − 1 " role="presentation"> di−1,j−1 个操作内将 X = X 1 ⋯ X i " role="presentation"> X=X1⋯Xi 转换为 Y 1 ⋯ Y j " role="presentation"> Y1⋯Yj
- 如果 X i ≠ Y j " role="presentation"> Xi≠Yj,则必然可在 d i − 1 , j − 1 + 1" role="presentation"> di−1,j−1+1 个操作内将 X = X 1 ⋯ X i " role="presentation"> X=X1⋯Xi 转换为 Y 1 ⋯ Y j " role="presentation"> Y1⋯Yj。这里的 + 1" role="presentation"> +1 操作表示将 X i " role="presentation"> Xi 替换为 Y j " role="presentation"> Yj
取上面三种情形的最小值,便是字符串 X" role="presentation"> X 和 Y" role="presentation"> Y 的最小编辑距离:
在编辑距离计算的过程中,通常采用二维矩阵来存储计算过程中子问题的解。
由以上分析,我们可以得知,当 x[i] == y[j] 时,有:
dp[i][j] = min(dp[i][j-1] + 1, dp[i-1][j] + 1, dp[i-1][j-1])
当 x[i] != y[j] 时,有:
dp[i][j] = min(p[i][j-1] + 1, dp[i-1][j] + 1, dp[i-1][j-1] + 1)
当 x 或 y 为空串时,有:
dp[0][j] = j, dp[i][0] = i
二、代码实现
下面是使用 C++ 实现的求解编辑距离的算法,其时间复杂度是 O ( m n )" role="presentation"> O(mn):
public class Solution {
public int distance(String src, String dest) {
int m = src.length(), n = dest.length();
int[][] dp = new int[m+1][n+1];
// 初始化空字符串的情况
for (int i = 1; i <= m; i++) {
dp[i][0] = i;
}
for (int j = 1; j <= n; j++) {
dp[0][j] = j;
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
int insertion = dp[i][j-1] + 1;
int deletion = dp[i-1][j] + 1;
int substitution = dp[i-1][j-1] + (src.charAt(i - 1) == dest.charAt(j - 1) ? 0 : 1);
dp[i][j] = Math.min(substitution, Math.min(insertion, deletion));
}
}
return dp[m][n];
}
}