动态规划(dynamic programming)之:edit-distance(word1变成word2的最小步骤数)

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:
Insert a character(插入)
Delete a character(删除)
Replace a character(代替)
Example
Given word1 = "mart" and word2 = "karma", return 3

题解1 - 双序列动态规划
两个字符串⽐较,求最值,直接看似乎并不能直接找出解决⽅案,这时往往需要使⽤动态规划的思想寻找递推关系。使⽤双序列动态规划的通⽤做法,不妨定义 f[i][j] 为字符串1的前 i 个字符和字符串2的前 j 个字符的编辑距离,那么接下来寻找其递推关系。增删操作互为逆操作,即增或者删产⽣的步数都是⼀样的。故初始化时容易知道 f[0][j] = j, f[i][0] = i , 接下来探讨 f[i][j]和 f[i - 1][j - 1] 的关系,和 LCS 问题类似,我们分两种情况讨论,即 word1[i] == word2[j]与否,第⼀种相等的情况有:
1. i == j , 且有 word1[i] == word2[j] , 则由 f[i - 1][j - 1] -> f[i][j] 不增加任何操作,有 f[i][j] = f[i - 1][j - 1] .
2. i != j , 由于字符数不等,肯定需要增/删⼀个字符,但是增删 word1 还是 word2 是不知道的,
故可取其中编辑距离的较⼩值,即 f[i][j] = 1 + min{f[i - 1][j], f[i][j - 1]} .
第⼆种不等的情况有:
1. i == j , 有 f[i][j] = 1 + f[i - 1][j - 1] .
2. i != j , 由于字符数不等,肯定需要增/删⼀个字符,但是增删 word1 还是 word2 是不知道的,
故可取其中编辑距离的较⼩值,即 f[i][j] = 1 + min{f[i - 1][j], f[i][j - 1]} .
最后返回 f[len(word1)][len(word2)]

class Solution {
public:
    int minDistance(string word1, string word2) {
        if(word1.empty())
           return word2.size();
        if(word2.empty())
           return word1.size();
        
        int len1 = word1.size();
        int len2 = word2.size();
        vector<vector<int> > f(len1+1,vector<int>(len2+1, 0));
        
        for(int i = 0; i <= len1; ++i)
            f[i][0] = i;
        for(int j = 0; j <= len2; ++j)
            f[0][j] = j;
        
        for(int i = 1; i <= len1; i++){
            for(int j = 1; j <= len2; j++){
                if(word1[i-1] == word2[j-1]){
                    f[i][j] = f[i-1][j-1];
                }else
                    f[i][j] = 1 + min(f[i-1][j-1], min(f[i-1][j], f[i][j-1]));
            }
        }
        return f[len1][len2];
    }
};

或者为下面这个: 

    int minDistance(string word1, string word2) {
        int len1=word1.length();
        int len2=word2.length();
        
        vector<vector<int>>dp(len1+1,vector<int>(len2+1));
        for(int i=0;i<=len1;i++){
            for(int j=0;j<=len2;j++){
                if(i==0){
                    dp[i][j]=j;   //如果 i=0 则需要插入j个字符
                }else if(j==0){
                    dp[i][j]=i;    //如果j=0则需要删除i个字符
                }else if(word1[i-1]==word2[j-1]){   //如果字符相同则不做变换,等于这个字符之前的步数
                    dp[i][j]=dp[i-1][j-1];
                }else{                          //否则 就从插入,删除,修改中选择最小的 加 1 
                    dp[i][j]=min(min(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1])+1;
                }
            }
        }
        return dp[len1][len2];
    }

猜你喜欢

转载自blog.csdn.net/ypshowm/article/details/89343948