Studying-代码随想录训练营day45| 115.不同的子序列、583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结篇

news2024/9/9 1:37:21

第45天,子序列part03,编辑距离💪(ง •_•)ง,编程语言:C++

目录

115.不同的子序列

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

72. 编辑距离

编辑距离总结篇


115.不同的子序列

文档讲解:代码随想录不同的子序列

视频讲解:手撕不同的子序列

题目:115. 不同的子序列 - 力扣(LeetCode)

学习:本题是392.判断子序列题目的扩展,本题需要求t在s中出现的次数。首先我们需要确定的就是t是否在s中出现。本题如果不是子序列,而是连续序列,可以考虑采用KMP算法进行求解。

从动归五部曲出发进行求解:

1.确定dp数组,以及下标的含义:本题可设置一个二维数组,dp[i][j]表示以i - 1为结尾的s的子序列中以j - 1为结尾的t出现的个数为dp[i][j]。

2.确定递归公式:首先我们在遍历的过程中需要判断的是s[i - 1] 和 t[j - 1]是否相等。假如相等,那么首先可以确定dp[i][j] 是可以由 dp[i - 1][j - 1]推导而来;其次还可以由dp[i - 1][j]推导而来。此处的含义就在于,是否要使用s[i - 1] = t[j - 1],如果不使用这个,我们就需要dp[i - 1][j]来判断,如果使用则是dp[i - 1][j - 1],最后得到:dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]

如果s[i - 1]与t[i - 1]不等,则说明当前未匹配,我们只能依靠dp[i - 1][j]。

3.初始化dp数组:显然根据递推公式,我们需要初始化第一行和第一列。第一行表示s为空串的时候,t出现的个数,显然为0;第一列表示t为空串的时候,在s中出现的个数,显然为1个。因此我们可在创建数组的时候,初始化为0,后把第一列,赋值为1,

4.确定遍历顺序,根据递推公式,我们需要依靠上方和左上方的元素,因此我们应该从上到下,从左到右进行遍历。

5.举例推导dp数组:

代码:

//时间复杂度O(m*n)
//空间复杂度O(m*n)
class Solution {
public:
    int numDistinct(string s, string t) {
        //动态规划,难题,很难
        //1.设置dp数组以及下标的含义
        vector<vector<uint64_t>> dp(s.size() + 1, vector<uint64_t>(t.size() + 1, 0));
        //2.确定递推公式
        //当s[i - 1] 与 t[j - 1]相等时,dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
        //当s[i - 1] 与 t[j - 1]不相等时,dp[i][j] = dp[i - 1][j];
        //3.初始化dp数组:初始化第一行和第一列
        //dp[i][0] 表示空字符串,[0-(i-1)]出现的个数,显然为1
        for(int i = 0; i <= s.size(); i++) {
            dp[i][0] = 1;
        }
        //dp[0][j] 表示[0-(j-1)],在空字符串中出现的个数,显然为0
        //4.确定遍历顺序
        for(int i = 1; i <= s.size(); i++) {
            for(int j = 1; j <= t.size(); j++) {
                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 - 1][j];
                }
            }
        }
        return dp[s.size()][t.size()];
    }

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

文档讲解:代码随想录两个字符串的删除操作

视频讲解:手撕两个字符串的删除操作

题目:583. 两个字符串的删除操作 - 力扣(LeetCode)

学习:首先本题有一个直观的思路,本题要通过删除字符使得两个字符串相同,则我们可以先求得两个字符串的最长公共子序列。之后每个字符串都需要删减到最长公共子序列的长度即可,最后所需要的最小步数就为:两个字符串的长度之和 - 最长公共子序列*2。

其次本题还可以通过动态规划的办法进行求解:

1.确定dp数组以及下标的含义:本题我们同样可以设置一个二维dp数组,dp[i][j]表示以 i - 1结尾的字符串word1和以 j - 1结尾的字符串word2相同所需要的最少步骤。

2.确定递推公式:首先遍历过程需要判断的是word1[i - 1] 和 word2[j - 1]是否相等。

如果word1[i - 1]与word2[j - 1]相等,则说明当前元素的是相同,那么我们只要保证前面的元素相同就行,因此最少步骤应该为dp[i - 1][j - 1];

如果word1[i - 1]与word2[j - 1]不相等,则说明当前元素是不等的,我们需要进行删除操作。我们可以选择删除word1[i-1[也可以选择删除word2[j-1],当然我们也可以选择两个都删除,只不过,两个都删除的情况,是包含在每个单独删除的情况里面的。然后我们选最少的步骤,则应该是:dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i][j] + 2)

3.递推公式初始化:根据递推公式,我们需要依靠左上方,上方,和左边的元素,因此我们应该初始化第一行和第一列。首先第一行表示:word1在是空串的时候,word2需要进行删除的操作,显然word2需要删除到成为空串,则应该是dp[0][j] = j。同理第一列表示word2为空串的时候,则dp[i][0] = i;

4.确定遍历顺序:显然需要从上到下,从左到右进行遍历。

5.举例推导dp数组:

代码:

//时间复杂度O(n*m)
//空间复杂度O(n*m)
class Solution {
public:
    int minDistance(string word1, string word2) {
        //动态规划,难题
        //1.确定dp数组以及下标的含义
        vector<vector<int>> dp(word1.size() + 1, vector<int> (word2.size() + 1, 0));
        //2.确定递推公式:判断两种情况
        //当word1[i - 1] 与 word2[j - 1]相同的时候:dp[i][j] = dp[i - 1][j - 1];
        //当word1[i - 1] 与 word2[j - 1]不相同的时候:dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);
        //3.初始化dp数组,初始化第一行和第一列
        for(int i = 0; i <= word1.size(); i++) {
            dp[i][0] = i;
        }
        for(int j = 0; j <= word2.size(); j++) {
            dp[0][j] = j;
        }
        //4.确定遍历顺序
        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. 编辑距离

文档讲解:代码随想录编辑距离

视频讲解:手撕编辑距离

题目: 72. 编辑距离 - 力扣(LeetCode)

学习:本题是前面题目的集大成之题,是动态规划解决的经典题目之一 。本题允许删除,替换,插入三个操作。前面的题型一般只包含一个字符串的删除操作,或者两个字符串的删除操作,因此本题实际上只是对于字符串需要考虑的操作要多一项。

从动归五部曲出发进行分析:

1.确定dp数组以及下标的含义:本题我们可以设置一个二维dp数组,dp[i][j]表示以i - 1结尾的字符串word1,和以j - 1结尾的字符串word2,最近的编辑距离为dp[i][j](变成相同字符串所需要的步骤)。

2.确定递推公式:我们在遍历的过程中,同样是需要比较word1[i - 1]和word2[j - 1]。

word1[i - 1]和word2[j - 1]相等,则不需要操作,则dp[i][j] = dp[i - 1][j - 1]

word1[i - 1]和word2[j - 1]不相等,则需要进行操作,需要注意插入和删除实际上是一个操作,因为删除一个项相等和插入一个项使其相等,所需要的步骤是一样的,因此三个步骤可以简化为两个步骤:删除(插入)和替换。对于删除操作来说,可以选择删除word1[i - 1],也可以选择删除word2[j - 1]对于替换来说就是将当前的数替换为相等的,则应该是dp[i-1][j - 1] + 1; 综上:dp[i][j] = min(dp[i - 1][j] + 1, min(dp[i][j - 1] + 1, dp[i - 1][j - 1] + 1));

3.初始化dp数组,显然我们需要初始化第一行和第一列,对于第一行来说,表示word1为空时,需要的操作,显然dp[0][j] = j; 对于第一列来说,表示word2为空时,需要的操作,显然dp[i][0] = i。

4.确定遍历顺序,显然我们需要从上往下,从左往右进行遍历

5.距离dp数组:

代码:

//时间复杂度O(n*m)
//空间复杂度O(n*m)
class Solution {
public:
    int minDistance(string word1, string word2) {
        //动态规划,很难
        //1.确定dp数组以及下标含义
        vector<vector<int>> dp(word1.size() + 1, vector<int> (word2.size() + 1, 0));
        //2.确定递推公式
        //3.初始化dp数组:初始化行和列
        for(int i = 0; i <= word1.size(); i++) {
            dp[i][0] = i;
        }
        for(int j = 0; j <= word2.size(); j++) {
            dp[0][j] = j;
        }
        //4.确定遍历顺序
        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()];
    }
};

编辑距离总结篇

文档讲解:代码随想录编辑距离总结

编辑距离是动态规划的经典例题之一,我们需要十分注意。

在做编辑距离题目之前,我们首先通过了三道题进行铺垫。

392.判断子序列:本题告诉了我们如果判断一个序列是否为另一个的子序列。从题意中我们也可以发现,只需要计算删除的情况,不用考虑增加和替换的情况,而且是只针对t序列的删除。最后我们想要找到的就是最长公共子序列的长度等于s.size()。

115.不同的子序列:本题要计算s在t出现的个数,本题和上一题基本上是一样的,只是要多考虑次数的情况。

583.两个字符串的删除操作:本题增加了对两个字符串的删除操作,整体思路不变。

72.编辑距离:本题增加了替换的操作,需要考虑的部分增加了,最终解决编辑距离问题。

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

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

相关文章

高效能程序员的9个习惯

最近看了一本关于敏捷软件开发实践的指南&#xff0c;他文中主要是在帮助软件开发者和团队提升工作效率、提高产品质量&#xff0c;并建立良好的工作文化和协作模式。以下是根据目录整理出的一段总结&#xff1a; 书名&#xff1a;《敏捷之道》 本书深入探讨了敏捷开发的核心原…

从 1 到 100 万+连接数,DigitalOcean 负载均衡的架构演进

在前不久&#xff0c;DigitalOcean 全球负载均衡器&#xff08;GLB&#xff09;Beta版正式上线。该解决方案能给客户的跨区域业务带来更好的支持&#xff0c;可以增强应用程序的弹性&#xff0c;消除单点故障&#xff0c;并大幅降低终端用户的延迟。这是 DigitalOcean 负载均衡…

Python写UI自动化--playwright(pytest.ini配置)

在 pytest.ini 文件中配置 playwright 的选项可以更好地控制测试执行的过程。 在终端输入pytest --help&#xff0c;可以找到playwright的配置参数 目录 1. --browser{chromium,firefox,webkit} 2. --headed 3. --browser-channelBROWSER_CHANNEL 4. --slowmoSLOWMO 5. …

魔众文库-PHP文库管理系统

魔众文库是一套基于PHPMYSQL开发的适用于多平台的文档管理系统&#xff0c;提供doc、ppt、excel、pdf、压缩包、图片、CAD 等资源的在线预览和下载&#xff0c;文件被转换为H5或图片格式&#xff0c;文字放大无失真&#xff0c;响应速度更快速对SEO更友好&#xff0c;收录更快、…

NFTScan | 07.22~07.28 NFT 市场热点汇总

欢迎来到由 NFT 基础设施 NFTScan 出品的 NFT 生态热点事件每周汇总。 周期&#xff1a;2024.07.22~ 2024.07.28 NFT Hot News 01/ 数据&#xff1a;NFT 系列 Liberty Cats 地板价突破 70000 MATIC 7 月 22 日&#xff0c;据 Magic Eden 数据&#xff0c;NFT 系列 Liberty C…

内网隧道学习笔记

1.基础&#xff1a; 一、端口转发和端口映射 1.端口转发是把一个端口的流量转发到另一个端口 2.端口映射是把一个端口映射到另一个端口上 二、http代理和socks代理 1.http带那里用http协议、主要工作在应用层&#xff0c;主要用来代理浏览网页。 2.socks代理用的是socks协议、…

c# string记录

c# srting 的操作例子 在C#中&#xff0c;string 类型是一个不可变&#xff08;immutable&#xff09;的引用类型&#xff0c;表示文本。由于它的不可变性&#xff0c;对字符串的任何修改操作实际上都会返回一个新的字符串实例。以下是一些常见的 string 操作例子&#xff1a; …

Hvv第二周,喝了3瓶红牛,心慌、头晕,我还行么?

Hvv第二周了&#xff0c;你们的物资挥霍的怎么样了啊&#xff1f;今天看到群里有小伙伴说喝了3瓶红牛&#xff0c;结果现在搞得头晕晕的&#xff0c;很慌。 Hvv物资来由 这不仅让我想来聊聊护网物资的来由和发展&#xff0c;也让后来进入网安这个行业的小伙伴了解一下&#xf…

【Plotly-驯化】一文教您画出Plotly中动态可视化饼图:pie技巧

【Plotly-驯化】一文教您画出Plotly中动态可视化饼图&#xff1a;pie技巧 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 免费获取相关内…

逻辑漏洞复现(pikachu靶场,大米cms)

逻辑漏洞 漏洞介绍 1.成因 逻辑漏洞是指由于程序逻辑不严或逻辑太复杂&#xff0c;导致一些逻辑分支不能够正常处理或处理错误&#xff0c;一般出现任意密码修改&#xff08;没有旧密码验证&#xff09;、越权访问、密码找回、交易支付金额等。 2. 分析 对常见的漏洞进行过…

Qt Phonon多媒体框架详解及简单实例分享

目录 1、Phonon 简介 2、Phonon基本类 2.1、VideoPlayer类 2.2、MediaObject类 2.3、Phonon::createPath() 2.4、AudioOutput类 2.5、VideoWidget Class 2.6、SeekSlider类 2.7、VolumeSlider类 3、Phonon 完整使用实例 4、总结 C++软件异常排查从入门到精通系列教程…

ChatGPT小狐狸AI付费创作系统v3.0.3+前端

小狐狸GPT付费体验系统的开发基于国外很火的ChatGPT&#xff0c;这是一种基于人工智能技术的问答系统&#xff0c;可以实现智能回答用户提出的问题。相比传统的问答系统&#xff0c;ChatGPT可以更加准确地理解用户的意图&#xff0c;提供更加精准的答案。同时&#xff0c;小狐狸…

项目管理“四管”法则

在项目管理中&#xff0c;“四管”的具体内容可能因不同的项目管理框架和实践而有所不同。但一般而言&#xff0c;它们可以概括为与项目成功密切相关的四个关键管理领域。以下是项目管理中“四管”&#xff1a; 一、人力资源管理&#xff08;管人&#xff09; 项目团队是项目…

AMQP-核心概念-终章

本文参考以下链接摘录翻译&#xff1a; https://www.rabbitmq.com/tutorials/amqp-concepts 连接&#xff08;Connections&#xff09; AMQP 0-9-1连接通常是长期保持的。AMQP 0-9-1是一个应用级别的协议&#xff0c;它使用TCP来实现可靠传输。连接使用认证且可以使用TLS保护…

Python 进行数据可视化(Matplotlib, Seaborn)

数据可视化是数据科学和分析中的重要工具&#xff0c;它通过图形表示数据&#xff0c;使得复杂的数据变得易于理解和分析。在Python中&#xff0c;最常用的两个数据可视化库是Matplotlib和Seaborn。 Matplotlib 1. 简介 Matplotlib是一个用于生成二维图形的Python库。它提供…

深入浅出消息队列----【阶段总结篇】

深入浅出消息队列----【阶段总结篇】 总览nameSrvBrokerproducer&#xff08;生产者&#xff09;consumer&#xff08;消费者&#xff09; 串联起来 本文仅是文章笔记&#xff0c;整理了原文章中重要的知识点、记录了个人的看法 文章来源&#xff1a;编程导航-鱼皮【yes哥深入浅…

小间距 LED 显示屏:引领显示技术新潮流

在现代显示技术领域&#xff0c;小间距LED显示屏以其先进的像素点控技术和卓越的显示效果&#xff0c;正逐渐成为市场的新宠。在此为您详细解析小间距LED显示屏相较于传统DLP背投显示屏的优势所在。 1、显示像素的完整性更高 在室内中高端显示市场中&#xff0c;DLP背投显示曾占…

PHP西陆招聘求职系统小程序源码

&#x1f525;【职场新宠】西陆招聘求职系统&#xff0c;你的职场加速器&#x1f680; &#x1f389;【开篇安利&#xff1a;一站式求职新体验】&#x1f389; 还在为找工作焦头烂额吗&#xff1f;是时候告别传统招聘网站的繁琐与低效了&#xff01;今天给大家种草一个超赞的…

1480. 找字典码最小的字符串

问题描述 编写程序&#xff0c;针对输入的 N 个不同的字符串&#xff0c;输出其中字典码最小的字符串。 输入 输入第一行给出正整数 N &#xff1b; 随后 N 行&#xff0c;每行给出一个长度小于 80 的非空字符串&#xff0c;其中不会出现换行符&#xff0c;空格&#xff0c…