首页 > 编程语言 >代码随想录算法训练营第五十九天 | 115.不同的子序列、583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结

代码随想录算法训练营第五十九天 | 115.不同的子序列、583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结

时间:2024-06-16 14:29:15浏览次数:12  
标签:元素 随想录 距离 编辑 word1 word2 字符串 dp size

115.不同的子序列

题目链接:代码随想录

视频讲解:动态规划之子序列,为了编辑距离做铺垫 | LeetCode:115.不同的子序列_哔哩哔哩_bilibili

解题思路

1.dp[i][j]    为在s的前i个元素(即s[0, i - 1])(以i-1结尾)中,有多少个t[0, j - 1]匹配(以t[j - 1]为结尾)

2.递推公式

//如果当前元素相等了,求s[0,i-2]中有多少个t[0,j-2] + 前面有多少个完整的t[0,j-1]

以"bag"举例           s前面有多少"ba" + 前面有多少个"bag"

if(s[i-1] == t[j-1])   dp[i][j] =  dp[i-1][j-1]  + dp[i-1][j]

else dp[i][j] = dp[i][j]  = dp[i-1][j]       //模拟删除了i-1这个元素

//如果当前元素不相等了,那么就之前看s[0,i-2]中有多少个t[0,j-1]

还是"bag"为例,那么就求s里面有多少个"bag"

3.初始化

当t为空字符串 dp[i][0] = 1       s中有一个空字符串

当s为空字符串 dp[0][j] = 0 

dp[0][0] = 1    都为空字符串

4.遍历顺序

从前往后,结果在s.size()和t.size()中 

 

 

class Solution {
private:
    const long long mod = 10e9+7;
public:
    int numDistinct(string s, string t) {
         vector<vector<long>> dp(s.size()+1,vector<long>(t.size()+1,0));
         for(int i = 0 ;i <=s.size() ; i++)
         {
             dp[i][0] = 1 ;
         }
         for(int j = 0 ; j<=t.size() ; j++)
         {
             dp[0][j] = 0;
         }
         dp[0][0] = 1;   //都为空字符串
         for(int i =1 ;i <=s.size() ; i++)
         {
                for(int j = 1 ; j<=t.size() ; j++)
                {
                        //如果当前字符都相同,那么就去看前面[0,i-2]有没有[0,j-2]
                        //同时也可以不使用这个字符,去判断前面有没有[0,j-1]
                        if(s[i-1]==t[j-1])  dp[i][j] = (dp[i-1][j-1] + dp[i-1][j]) % mod;
                        //如果不相同,就相当于删除这个字符,看前面的
                        else dp[i][j] = dp[i-1][j] % mod;
                        
                }
         }
         //最后结果肯定是在结尾,因为是个区间
         return dp[s.size()][t.size()];
    }
};

583. 两个字符串的删除操作

题目链接:代码随想录

视频讲解:动态规划之子序列,还是为了编辑距离做铺垫 | LeetCode:583.两个字符串的删除操作_哔哩哔哩_bilibili

解题思路

这题是两个字符串都可以删

1.dp[i][j]                  需要比较两个字符串的长度,因此需要二维数组

                               以i-1为结尾的word1([0,i-1]),以j-1为结尾的word2([0,j-1])的最小操作数

2.递推公式

当前元素相等,那么就不需要操作,那么就和[0,i-2]和[0,j-2]的操作数

if(word1[i-1] == word2[j-1] )   dp[i][j] = dp[i-1][j-1]      

元素不相等了,此时要进行删除操作

有三种情况,删word1                删word2 (先word1,再删word2,就是都删了的情况)

else dp[i][j] = min (dp[i-1][j] + 1 , dp[i][j-1] + 1)   //取最小的操作数

3.初始化

dp[0][j] =  j;                dp[i][0] = i;   第一列第一行,面对空字符串,那么有多少个元素,就要操作多少次

4.递推公式

从左到右,从上到下

class Solution {
public:
    int minDistance(string word1, string word2) {
            vector<vector<int>> dp(word1.size()+1 , vector<int>(word2.size()+1 , 0));
            //当word2为空字符串
            for(int i = 0 ;  i<=word1.size() ; i++)
            {
                 dp[i][0] = i;   //有多少个字符就删几个
            }
            //word1为空字符串
            for(int j =0 ; j<=word2.size() ; j++)
            {
                dp[0][j] = j ;    //有多少个就删几次
            }
            for(int i =1 ; i<=word1.size();  i++)
            {
                for(int j = 1; j<=word2.size() ; 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]+1 , dp[i][j-1]+1);  //不相同就选一个删,取最小的
                }
            }
            return dp[word1.size()][word2.size()];
    }
};

72. 编辑距离

题目链接:代码随想录

视频讲解:动态规划终极绝杀! LeetCode:72.编辑距离_哔哩哔哩_bilibili

解题思路

1.dp[i][j]      以i-1结尾的word1([0,i-1]),以j-1为结尾的word2([0,j-1])的最小操作次数

2.递推公式

//如果元素相同

if(word1[i-1] == word2[j-1])     dp[i][j] = dp[i-1][j-1]     //元素相同,那么就不需要操作

如果不相同

我们有增,删,替换三种操作

删一个元素 dp[i][j] = dp[i-1][j] + 1;     //操作word1删除当前元素,次数+1

增一个元素 (逆向考虑,word1增加一个元素,相当于word2减去一个元素的操作次数是一样的)

                     dp[i][j] = dp[i][j-1] + 1;

替换一个元素  dp[i][j] = dp[i-1][j-1] + 1     //替换后,我们i-1位置的元素相同了,再做一个+1的操作

else 这三种取最小值即可

3.初始化

dp[i][0] = i ;                dp[0][j] = j;     //其中一个有空字符串,那么有多少个元素就操作多少次

4.遍历顺序

从左到右,从上到下

 

class Solution {
public:
    int minDistance(string word1, string word2) {
            vector<vector<int>> dp(word1.size()+1 , vector<int>(word2.size()+1,0));
            for(int i = 0 ;i<=word1.size() ; i++) dp[i][0] = i;
            for(int j = 0 ;j<=word2.size() ; j++) dp[0][j] = j;
            for(int i =1 ;i<= word1.size(); i++)
            {
                for(int j =1 ; j<=word2.size(); 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]+1 , min(dp[i][j-1]+1 , dp[i-1][j-1]+1));
                }
            }
            return dp[word1.size()][word2.size()];
    }
};

编辑距离总结

代码随想录

标签:元素,随想录,距离,编辑,word1,word2,字符串,dp,size
From: https://blog.csdn.net/m0_73815931/article/details/139669174

相关文章