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

分析(错误)

将word1转换成word2,无法缺少的步骤是删除或者插入,从而使得两者的长度一致。在此前提下,如何尽可能利用word2中原有的字符才是关键。所以本题可以转换为:寻找在word2中与word1中相同且依次出现的多字符个数(可以不连续也可以跳过)。
后来按照这个思路完成的一次实现中,发现了反例……例如word1为"ab",word2为"bc"则该思路不成立。

分析二

直接考虑两个字符串之间的最小转化距离。若已知字符串A和字符串B的最小转化距离为dp[i-1][j-1],则考虑添加一个字母之后的字符串Ax和By的最小转化距离dp[i][j]。

  • 若x==y,则有dp[i][j]=dp[i-1][j-1]
  • 若x!=y,则有三种情况
    1)将x替换为y,则有dp[i][j]=dp[i-1][j-1]+1
    2)删去x,则有dp[i][j]=dp[i-1][j]+1
    3)添加y,则有dp[i][j]=dp[i][j-1]+1
    取三者最小值即可,得到此时状态转移方程为
    dp[i][j]=min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1])+1

实现

class Solution {
public:
    int minDistance(string word1, string word2) {
        int m=word1.size(), n=word2.size(), dp[m+1][n+1];
        for(int i=0; i<=m; i++)
            dp[i][0] = i;
        for(int j=0; j<=n; j++)
            dp[0][j] = j;
        for(int j=1; j<=n; j++){
            for(int i=1; i<=m; i++){
                if(word1[i-1]==word2[j-1])
                    dp[i][j] = dp[i-1][j-1];
                else
                    dp[i][j] = min(dp[i-1][j-1], min(dp[i-1][j], dp[i][j-1])) + 1;
            }
        }
        return dp[m][n];
    }
};

思考

动态规划真的是,没想出来的时候觉得难死。想出来了觉得豁然开朗。虽然过程很痛苦,但是完成之后所获得的成就感也是巨大的。

你可能感兴趣的:(72. Edit Distance)