0
点赞
收藏
分享

微信扫一扫

编辑距离专题

无聊到学习 2022-03-30 阅读 41

母题

给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

  • 插入一个字符
  • 删除一个字符
  • 替换一个字符

示例 1:

输入:word1 = “horse”, word2 = “ros”
输出:3
解释:
horse -> rorse (将 ‘h’ 替换为 ‘r’)
rorse -> rose (删除 ‘r’)
rose -> ros (删除 ‘e’)

思考

这种问题好复杂啊,一拿上来,不会做啊,很尴尬。
假设s=“horse”, t=“rose”
我们从尾巴看起。
假设我们知道“hors”和“ros”的最小编辑距离为d,那么“horse”和“rose”的编辑距离就是d了,因为最后一个字符都相同了,还编辑个屁啊。

好了,现在转为求“hors”和“ros”的最小编辑距离了,我们又注意到最后字母都一样,所以d=distance(“hor”,“ro”)了。

现在“hor”和“ro”的编辑距离咋算呢?这个时候,他们的末尾字母不再相同了。
既然不同,那我们就通过编辑操作让他们的末尾相同呗。题目是支持删除、插入和替换的。
要通过“删除、插入、替换”操作让“hor”和“ro”的末尾相同,可以咋做呢?

  • 删除“hor”的尾巴,然后计算“ho”和“ro”的最小编辑距离 加上这一步的代价1,此时两个串变成了“ho”和“ro”了。这个操作也等价于在“ro”的末尾插入r。
  • 删除“ro”的尾巴,认为“ro”的“o”是多余的,此时计算“hor”和“r”的编辑距离,加上这一步的代价1。
  • 同时删除两个串的尾巴,其实就是等价于替换两个串的尾巴为相同的字符,加上这一步的代价1。

然后我们再取这三个操作的最小就行了。

class Solution {
public:
    int minDistance(string word1, string word2) {
        vector< vector<short> > dp; 
        int m = word1.size();
        int n = word2.size();

        // 1. 初始化dp,dp应该包含[m+1,n+1]个元素
        for(int i =0;i<=m;i++){
            dp.push_back(vector<short> (n+1, 0));
            for(int j =0;j<=n;j++){
                // 2. dp[0,0..i]都应该初始化为i,
                dp[0][j]=j;
            }
            // 3. dp[0..i, 0]都初始化为i。表示空字符串与长度为i的字符串比较。
            dp[i][0] = i;
        }
        for(int i =1;i<=m;i++){
            for(int j =1;j<=n;j++){
                if(word1[i-1] == word2[j-1]){
                    dp[i][j] = dp[i-1][j-1];
                }
                else{
                    dp[i][j] = min(min(dp[i-1][j], dp[i][j-1]), dp[i-1][j-1]) + 1;
                }
            }
        }
        return dp[m][n];
    }
};

变形1: 583 两个字符串的删除操作

https://leetcode-cn.com/problems/delete-operation-for-two-strings/
此时就只能删除,于是尾巴不同的时候只有两种操作:

  • 删除“hor”的尾巴,然后计算“ho”和“ro”的最小编辑距离 加上这一步的代价1,此时两个串变成了“ho”和“ro”了。这个操作也等价于在“ro”的末尾插入r。
  • 删除“ro”的尾巴,认为“ro”的“o”是多余的,此时计算“hor”和“r”的编辑距离,加上这一步的代价1。
class Solution {
public:
    int minDistance(string word1, string word2) {
        vector< vector<short> > dp; 
        int m = word1.size();
        int n = word2.size();

        // 1. 初始化dp,dp应该包含[m+1,n+1]个元素
        for(int i =0;i<=m;i++){
            dp.push_back(vector<short> (n+1, 0));
            for(int j =0;j<=n;j++){
                // 2. dp[0,0..i]都应该初始化为i,
                dp[0][j]=j;
            }
            // 3. dp[0..i, 0]都初始化为i。表示空字符串与长度为i的字符串比较。
            dp[i][0] = i;
        }
        for(int i =1;i<=m;i++){
            for(int j =1;j<=n;j++){
                if(word1[i-1] == word2[j-1]){
                    dp[i][j] = dp[i-1][j-1];
                }
                else{
                    dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + 1;
                }
            }
        }
        return dp[m][n];
    }
};

变形2: 712. 两个字符串的最小ASCII删除和

https://leetcode-cn.com/problems/minimum-ascii-delete-sum-for-two-strings/
一样的分析,只是每一步删除、插入的代价不同了。

class Solution {
public:
    int minDistance(string word1, string word2) {
        vector< vector<int> > dp; 
        int m = word1.size();
        int n = word2.size();

        // 1. 初始化dp,dp应该包含[m+1,n+1]个元素
        for(int i =0;i<=m;i++){
            dp.push_back(vector<int> (n+1, 0));
            for(int j =0;j<=n;j++){
                // 2. dp[0,0..i]都应该初始化为i,
                if(j>0)
                    dp[0][j]= dp[0][j-1] + word2[j-1];
                else
                    dp[0][j]=0;
            }
            // 3. dp[0..i, 0]都初始化为i。表示空字符串与长度为i的字符串比较。
            if(i>0)
                dp[i][0] = dp[i-1][0] + word1[i-1];
            else{
                dp[i][0] = 0;
            }
        }
        for(int i =1;i<=m;i++){
            for(int j =1;j<=n;j++){
                if(word1[i-1] == word2[j-1]){
                    dp[i][j] = dp[i-1][j-1];
                }
                else{
                    dp[i][j] =min(dp[i-1][j] + word1[i-1], dp[i][j-1]+ word2[j-1]);
                }
            }
        }
        return dp[m][n];
    }
    int minimumDeleteSum(string s1, string s2) {
        return minDistance(s1, s2);
    }
};
举报

相关推荐

0 条评论