【dp】不同的子序列 & 两个字符串的删除操作 & 编辑距离

这篇具有很好参考价值的文章主要介绍了【dp】不同的子序列 & 两个字符串的删除操作 & 编辑距离。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

115. 不同的子序列

【dp】不同的子序列 & 两个字符串的删除操作 & 编辑距离

  • dp[i][j]:以j-1为结尾的t出现在以i-1为结尾的s子序列的个数

需要开辟m+1行,n+1列的二维数组


为啥状态方程是:

  • s[i] == t[j] 时 dp[i][j] = dp[i-1][j-1] + dp[i-1][j]

  • s[i] != t[j] 时 dp[i][j] = dp[i-1][j]

先看s[i] == t[j] 时,以s = “rara” t = “ra” 为例,当i = 3, j = 1时,s[i] == t[j]
此时分为2种情况:s串用最后一位的a 以及 不用最后一位的a

  • 如果用s串最后一位的a,那么t串最后一位的a也被消耗掉,此时的子序列其实=dp[i-1][j-1]

  • 如果不用s串最后一位的a,那就得看"rar"里面是否有"ra"子序列的了,就是dp[i-1][j]

所以 dp[i][j] = dp[i-1][j-1] + dp[i-1][j]

再看s[i] != t[j] 比如 s = “rarb” t = “ra” 还是当i = 3, j = 1时,s[i] != t[j]

此时显然最后的b想用也用不上啊。所以只能指望前面的"rar"里面是否有能匹配"ra"的

所以此时dp[i][j] = dp[i-1][j]


如果当前字符s[i - 1]和 t[i - 1]相等,则可以使用当前字符匹配,并使用s[0]~s[i - 2]匹配t[0]~t[j - 2],即dp[i - 1][j - 1]。还可以不使用当前字符s[i - 1]匹配,使用s[0]~s[i - 2]匹配t[0]~t[j - 1],即dp[i - 1][j]

如果当前字符s[i - 1]和 t[i - 1]不相等,则不能使用当前字符s[i - 1]匹配,需要使用s[0]~s[i-2]匹配t[0]~t[j-1],即dp[i-1][j]

【dp】不同的子序列 & 两个字符串的删除操作 & 编辑距离

class Solution {
public:
    int numDistinct(string s, string t) {
        int m = s.size();
        int n = t.size();
        // dp[i][j]:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数
        vector<vector<uint64_t>> dp(m + 1, vector<uint64_t>(n + 1));
        // 空字符串出现在空字符串的次数
        dp[0][0] = 1;
        // t为空,空字符串出现在s中的次数
        for (int i = 1; i <= m; i++) dp[i][0] = 1;
        // s为空,t出现在空字符串中的次数
        for (int j = 1; j <= n; j++) dp[0][j] = 0;

        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (s[i - 1] == t[j - 1]) {
                    // 当前字符相等
                    // 用当前字符匹配,即使用s[0 ~ i-2]匹配t[0 ~ j-2] dp[i - 1][j - 1]
                    // 不用当前字符匹配,即使用s[0 ~ i-2]匹配t[0 ~ j-1] dp[i - 1][j]
                    dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
                } else {
                    // 不用当前字符匹配,即使用s[0 ~ i-2]匹配t[0 ~ j-1] dp[i - 1][j]
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }
        return dp[m][n];
    }
};

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

【dp】不同的子序列 & 两个字符串的删除操作 & 编辑距离

  • dp[i][j]:以i-1为结尾的字符串word1,和以j-1为结尾的字符串word2,想要达到相等,所需要删除元素的最少次数

【dp】不同的子序列 & 两个字符串的删除操作 & 编辑距离

class Solution {
public:
    int minDistance(string word1, string word2) {
        // dp[i][j]:以i-1为结尾的字符串word1,和以j-1位结尾的字符串word2,想要达到相等,所需要删除元素的最少次数
        // dp[i][j] = dp[i - 1][j - 1];
        // dp[i][j] = min({dp[i - 1][j - 1] + 2, dp[i - 1][j] + 1, dp[i][j - 1] + 1});
        int m = word1.size();
        int n = word2.size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
        dp[0][0] = 0;                              // word1、word2都为空串,删除0次相同
        for(int i = 1; i <= m; i++) dp[i][0] = i;  // word2为空串,word1[0~i-1]变成空串,需要删除i次
        for(int j = 1; j <= n; j++) dp[0][j] = j;  // word1为空串,word2[0~j-1]变成空串,需要删除j次
        for(int i = 1; i <= m; i++){
            for(int j = 1; j <= n; j++){
                if(word1[i - 1] == word2[j - 1]){
                	// 如果当前字符相等,则当前字符不用删除,word1[0] ~ word1[i - 1]和word2[0] ~ word2[j - 1]删除dp[i][j]次后相同
                	// 与word1[0] ~ word1[i - 12]和word2[0] ~ word2[j - 2]删除dp[i - 1][j - 1]次后相同
                	// 这两个删除次数应该相同
                    dp[i][j] = dp[i - 1][j - 1];
                }else{
                	// 若当前字符不相同,则要么是当前的两个字符都删除,变成word1[0] ~ word1[i - 2]和word2[0] ~ word2[j - 2]
                	// 要么是删除word1[i - 1],要么是word2[j - 1]
                	// 三个取最小值即可
                    dp[i][j] = min(dp[i - 1][j - 1] + 2, min(dp[i - 1][j] + 1, dp[i][j - 1] + 1));
                }
            }
        }
        return dp[m][n];
    }
};

72. 编辑距离

【dp】不同的子序列 & 两个字符串的删除操作 & 编辑距离文章来源地址https://www.toymoban.com/news/detail-413667.html

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

到了这里,关于【dp】不同的子序列 & 两个字符串的删除操作 & 编辑距离的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 算法刷题|583.两个字符串的删除操作、72.编辑距离

    题目:给定两个单词 word1 和 word2 ,返回使得 word1 和 word2 相同所需的最小步数。 每步 可以删除任意一个字符串中的一个字符。 dp[i][j] 表示以i-1结尾的word1子序列和以j-1结尾word2变成相同所需要的最小的步数为dp[i][j] 递推公式:分两种情况,word1.charAt(i-1) 和 word2.charAt(j-1)是否

    2024年02月08日
    浏览(39)
  • LeetCode | C++ 动态规划——583. 两个字符串的删除操作、72. 编辑距离

    583题目链接 做法一: 本题和1143.最长公共子序列基本相同,只要求出两个字符串的最长公共子序列长度即可,那么除了最长公共子序列之外的字符都是必须删除的,最后用两个字符串的总长度减去两个最长公共子序列的长度就是删除的最少步数。 做法二: 本题和115.不同的子

    2024年02月16日
    浏览(49)
  • 代码随想录第五十六天——两个字符串的删除操作,编辑距离

    题目链接:两个字符串的删除操作 两个字符串可以相互删除 版本一: 确定dp数组及下标的含义 dp[i][j] :以i-1为结尾的字符串word1,和以j-1为结尾的字符串word2,想要达到相等,所需要删除元素的最少次数 确定递推公式 (1)当word1[i - 1] 与 word2[j - 1]相同: (2)当word1[i - 1] 与

    2024年02月02日
    浏览(36)
  • 代码随想录打卡第56天|583. 两个字符串的删除操作;72. 编辑距离

    583. 两个字符串的删除操作 关键点1:dp数组的含义 dp[i][j],使得以i-1为结尾word1 和 以j-1为结尾的word2 相同所需的最小步数; 关键点2:递归公式的推导 if(nums1[i-1] == nums2[j-1]),则i和j同时移动,所以为i-1,j-1;dp[i][j] = dp[i-1][j-1];由于不需要进行删除操作,所以不需要加1 如果不相

    2023年04月19日
    浏览(48)
  • 算法刷题-字符串-重复的子字符串

    KMP算法还能干这个 力扣题目链接 给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母,并且长度不超过10000。 示例 1: 输入: “abab” 输出: True 解释: 可由子字符串 “ab” 重复两次构成。 示例 2: 输入: “aba” 输出: False 示

    2024年02月09日
    浏览(50)
  • (字符串 ) 459. 重复的子字符串——【Leetcode每日一题】

    难度:简单 给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。 示例 1: 输入: s = “abab” 输出: true 解释: 可由子串 “ab” 重复两次构成。 示例 2: 输入: s = “aba” 输出: false 示例 3: 输入: s = “abcabcabcabc” 输出: true 解释: 可由子串 “abc” 重复四次构

    2024年02月07日
    浏览(45)
  • C#从字符串中提取固定步长的子字符串

    C#从字符串中提取固定步长的子字符串 C#的Substring方法只能提取固定长度的子字符串,不能直接提取固定步长的子字符串。因此,我们需要自己编写一个方法来实现这个功能。 这个方法可以用于从字符串中提取固定步长的子字符串。例如,如果 str 是 \\\"HelloWorld\\\",finger 是 2,

    2024年02月05日
    浏览(43)
  • 【学会动态规划】环绕字符串中唯一的子字符串(25)

    目录 动态规划怎么学? 1. 题目解析 2. 算法原理 1. 状态表示 2. 状态转移方程 3. 初始化 4. 填表顺序 5. 返回值 3. 代码编写 写在最后: 学习一个算法没有捷径,更何况是学习动态规划, 跟我一起刷动态规划算法题,一起学会动态规划! 题目链接:467. 环绕字符串中唯一的子字

    2024年02月10日
    浏览(36)
  • 重复的子字符串

    目录 1.题目描述 2.题目求解 方法一:枚举 方法二:字符串匹配 方法三:另辟蹊径 给定一个非空的字符串  s  ,检查是否可以通过由它的一个子串重复多次构成。 示例 1: 示例 2: 示例 3: 提示: 1 = s.length = 104 s  由小写英文字母组成 先看一下官方给的两种解法: 方法一:枚

    2024年02月01日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包