求解编辑距离的动态规划算法

1,174 阅读4分钟
原文链接: myanbin.github.io

求解编辑距离的动态规划算法

Post on · 28 views · Edit it on Github

编辑距离(Edit Distance)是一种用于比较两个字符串之间相似度的计算方法,其定义为:将字符串 X 转换成字符串 Y 所需要的字符操作的最少次数,这里的操作是指插入(Insert)、删除(Delete)或替换(Substitute)。

比如,字符串 varyevery 的编辑距离是 2,因为可以通过以下的两步操作进行转换:

  1. 在串首插入字符 e,得到 evary
  2. 将字符 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。那么可知:

  1. 若在 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 中;

  2. 若在 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 中删除;

  3. 若在 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)

xy 为空串时,有:

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];
    }
}

三、参考资料