[LeetCode 72] Edit Distance(编辑距离/动态规划/DP)

72. Edit Distance

Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)

You have the following 3 operations permitted on a word:

a) Insert a character
b) Delete a character
c) Replace a character


题解

  本题是求两个字符串的编辑距离,粗略的感受一下题目,大概会觉得跟求最长公共子序列(LCS)类似。对于LCS问题,我们是用动态规划的方法解决的,因此这题我们也可以从动态规划的角度出发找思路。
  跟LCS问题一样,我们用dp[i][j]表示word1的长度为i的前缀与word2的长度为j的前缀的编辑距离。我们需要做的是对于dp[i][j]找到一个从dp[i-a][j-b]推进到dp[i][j]的方法。我们之所以可以认为一定是从前往后匹配,是因为任意两次编辑交换顺序不影响结果,因此我们总是先做匹配靠前字符的操作。
  因为题目给出的3种操作,都只影响1个字符,因此对于dp[i][j],我们可以认为他是从dp[i-1][j], dp[i][j-1], dp[i-1][j-1]中的一种状态转移过来的。对于前两者,显然还需要再进行一次插入或删除操作。对于后者,可能扩展的新字符刚好相等,否则需要一次编辑操作。
  因此我们得到公式
  dp(i,j)=min{dp(i-1,j)+1, dp(i,j-1)+1, dp(i-1,j-1)+(word1(i-1)!=word2(j-1))}
  
  容易分析,此算法的时间复杂度为O(n^2).


代码

class Solution {
public:
    int minDistance(string word1, string word2) {
        int m = word1.size();
        int n = word2.size();
        unsigned dp[m+1][n+1];
        memset(dp, -1, sizeof(dp));

        for (int i = 0; i <= n; i++) {
            dp[0][i] = i;
        }
        for (int i = 1; i <= m; i++) {
            dp[i][0] = i;
        }
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                dp[i][j] = min(dp[i-1][j]+1, dp[i][j-1]+1);
                dp[i][j] = min(dp[i][j], dp[i-1][j-1] + (word1[i-1]!=word2[j-1]));
            }
        }
        return dp[m][n];
    }
};

你可能感兴趣的:(OJ题解)