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

news2024/11/19 12:32:12

115. 不同的子序列

在这里插入图片描述

  • 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]

在这里插入图片描述

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[i][j]:以i-1为结尾的字符串word1,和以j-1为结尾的字符串word2,想要达到相等,所需要删除元素的最少次数

在这里插入图片描述

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. 编辑距离

在这里插入图片描述

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];
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/419005.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GDI+下字体大小自适应方案初探

在某个瞬间&#xff0c;我忽然发觉&#xff0c;三体或是AI&#xff0c;本质上是非常相近的事物&#xff0c;甚至在面对任何未知领域的时候&#xff0c;人类总会不自觉地划分为降临派、拯救派和幸存派。姑且不论马斯克等人叫停 GPT-5 的真实动机如何&#xff0c;当大语言模型(LL…

JMU Oracle实验四

用来记录实验操作的 spool E:\oracle_record\record20230406.txt ... spool off老师问的问题 让我展示了一下open_cursor的alter操作问我怎么查看spfile文件&#xff0c;实例&#xff0c;会话的参数内容就这两个 1. 采用不同的方法查询Oracle数据库当前使用的初始化参数文件…

仅三行就能学会数据分析——Sweetviz详解

文章目录前言一、准备二、sweetviz 基本用法1.引入库2.读入数据3.调整报告布局总结前言 Sweetviz是一个开源Python库&#xff0c;它只需三行代码就可以生成漂亮的高精度可视化效果来启动EDA(探索性数据分析)。输出一个HTML。 如上图所示&#xff0c;它不仅能根据性别、年龄等…

PHP 调用百度人脸对比

本文章主要介绍人脸对比API能力、应用场景、请求实例、参数说明。 接口能力 两张人脸图片相似度对比&#xff1a;比对两张图片中人脸的相似度&#xff0c;并返回相似度分值。 多种图片类型&#xff1a;支持生活照、证件照、身份证芯片照、带网纹照四种类型的人脸对比。 活体检测…

redis双写一致问题场景及方案

产生问题的场景 写入数据库后立即更新缓存&#xff08;较常见&#xff09; 这种场景下 问题产生的主要原因是写入数据库与更新缓存非原子性 有延迟 所以这样会导致谁更新缓存慢 谁会真正的更新缓存 更新数据库后立即删除缓存 查询时再插入缓存 与上一场景类似 虽然写入数据库…

C#,码海拾贝(18)——矩阵的(一般)三角分解法(Triangular Decomposition)之C#源代码,《C#数值计算算法编程》源代码升级改进版

1 三角分解法 Triangular Decomposition 三角分解法亦称因子分解法&#xff0c;由消元法演变而来的解线性方程组的一类方法。设方程组的矩阵形式为Axb&#xff0c;三角分解法就是将系数矩阵A分解为一个下三角矩阵L和一个上三角矩阵U之积&#xff1a;ALU&#xff0c;然后依次解…

Vue——模板引用

目录 访问模板引用​ v-for 中的模板引用​ 函数模板引用​ 组件上的 ref​ 虽然 Vue 的声明性渲染模型为你抽象了大部分对 DOM 的直接操作&#xff0c;但在某些情况下&#xff0c;我们仍然需要直接访问底层 DOM 元素。要实现这一点&#xff0c;我们可以使用特殊的 ref att…

Vue3技术3之setup的两个注意点、computed计算属性

Vue3技术3setup的两个注意点Vue2中的一些知识点App.vueDemo.vuesetup的两个注意点第一个注意点App.vueDemo.vue第二个注意点App.vueDemoTwo.vue总结computed计算属性App.vueDemo.vue总结setup的两个注意点 Vue2中的一些知识点 App.vue <template><div><h1>…

CnOpenData制造业单项冠军企业工商注册基本信息数据

一、数据简介 2016年3月&#xff0c;工信部印发《制造业单项冠军企业培育提升专项行动实施方案》&#xff0c;方案指出&#xff1a;“到2025年&#xff0c;总结提升200家制造业单项冠军示范企业&#xff0c;发现和培育600家有潜力成长为单项冠军的企业”。截至2022年&#xff0…

工程行业管理系统-专业的工程管理软件-提供一站式服务

Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目显示…

基于Python的简单40例和爬虫详细讲解(文末赠书)

目录 先来看看Python40例 学习Python容易坐牢&#xff1f; 介绍一下什么是爬虫 1、收集数据 2、爬虫调研 3、刷流量和秒杀 二、爬虫是如何工作的&#xff1f; 三、爬虫与SEO优化 什么是python爬虫 Python爬虫架构 最担心的问题 本期送书 随着人工智能以及大数据的兴起…

《JavaEE》HashTable、HashMap、ConcurrentHashMap

目录 HashTable HashMap ConcurrentHashMap ​编辑 HashTable与ConcurrentHashMap的区别 &#x1f451;作者主页&#xff1a;Java冰激凌 &#x1f4d6;专栏链接&#xff1a;JavaEE 进入到线程模块 必不可少的就是接触到线程安全的数据结构 例如StringBuffer、BlockingQueu…

计网第五章.运输层—TCP的拥塞控制

以下来自湖科大计算机网络公开课笔记及个人所搜集资料 目录一、拥塞控制与流量控制1.1 拥塞控制的目的1.2 区分拥塞控制与流量控制二、四种拥塞控制算法2.1 慢开始和拥塞避免2.2 快重传2.3 快恢复一、拥塞控制与流量控制 1.1 拥塞控制的目的 先看一下什么是拥塞&#xff1a; …

AVL树介绍

AVL树AVL树的概念AVL树结点的定义AVL树的插入AVL树的旋转&#xff08;1&#xff09;左单旋&#xff08;2&#xff09;右单旋&#xff08;3&#xff09;左右双旋&#xff08;4&#xff09;右左双旋AVL树的验证AVL树的性能AVL树的概念 二叉搜索树虽然可以提高我们查找数据的效率…

第三章 Linux实际操作——vi和vim编辑器

第三章 Linux实际操作——vi和vim编辑器3.1 vi和vim的基本介绍3.2 vi和vim常用的三种3.2.1 正常模式3.2.2 插入模式3.2.3 命令行模式3.3 vi和vim基本使用3.4 各种模式的相互切换3.5 vi和vim的快捷键3.1 vi和vim的基本介绍 Linux系统会内置 vi文本编辑器Vim具有程序编辑的能力&…

hadoop单机版安装

文章目录1. 将安装包hadoop-3.1.3.tar.gz上次至linux中2. 进行解压操作3. 修改目录名称4. 配置环境变量5. 使用官方提供的jar包实现wordcount案例1. 将安装包hadoop-3.1.3.tar.gz上次至linux中 2. 进行解压操作 tar -zxvf hadoop-3.1.3.tar.gz -C /opt/softs/##tar: 解压打包的…

TikTok听证会后:走不出的隐私风暴和出不了的海

TikTok听证会结束一周。 这场来自大洋彼岸的漩涡紧扣着中国科技圈的心弦&#xff0c;这不是一场稀松平常的热点&#xff0c;而是一次样本实例的演绎&#xff0c;每一个企图出海&#xff0c;扩展生意版图的中国企业们&#xff0c;都在密切关注&#xff0c;希望在TikTok身上找到…

快排非递归/归并排序/排序总结

一、非递归实现快排 在某些情景下&#xff0c;递归可以利用分治思想&#xff0c;将一个问题转化为多个子问题&#xff0c;再转化为更多个最小规模的子问题。从而帮助我们解决问题。 但是&#xff0c;递归可能在效率和内存上产生问题。现如今&#xff0c;由于编译器的进一步优化…

图像分割中的混淆矩阵和利用混淆矩阵计算指标

目录 1. 介绍 2. 创建混淆矩阵 2.1 update 方法 2.2 compute 方法 2.3 str 方法 3. 测试 4. 完整代码 1. 介绍 语义分割中&#xff0c;性能指标可以利用混淆矩阵进行计算 这里实现的方法和图像分类中不一样&#xff0c;需要的可以参考&#xff1a;混淆矩阵Confusion M…

大数据技术——spark集群搭建

目录 spark概述 spark集群搭建 1.Spark安装 2.环境变量配置 3.Spark集群配置 4.启动Spark集群 存在问题及解决方案 请参考以下文章 spark概述 Spark是一个开源的大数据处理框架&#xff0c;它可以在分布式计算集群上进行高效的数据处理和分析。Spark的特点是速度快、易…