代码随想录训练营第56天|583.两个字符串的删除操作、72.编辑距离

news/2025/2/7 6:07:03/

583.两个字符串的删除操作、72.编辑距离

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

思路1–最长公共子序列

对于该题,也许我们可以先求出两个字符串的最长公共子序列,让这两个序列变成这个最长公共子序列即可,这样直接用两个字符串的长度之和减去最长公共子序列长度的两倍即可。
本题就回归到了求最长公共子序列的问题了。
对此,我们已经做过很多求最长公共子序列的题目了。我们只讲思路即可。

对于两个数组中的每一个元素都有两种可能,
两个元素相等于或者不相等,如果两个元素相等,那么我们他的最长公共子序列应该等于左上元素(两个数组分别前一个元素对应的最长公共最序列)+1,这样表示可以得到更长的公共序列。
于此同时,如果两个元素不相等,那么这个元素应该更新为二维数组左边和上边的较大者,继承可能存在的最大子序列长度。

动态规划四部曲。
1.dp数组的含义。dp[ii][jj]表示text1中0-ii-1和text2中0-jj-1中最长公共子序列。
2.dp数组的递推公式。

if(text1[ii-1] == text2[jj-1])dp[ii][jj] = dp[ii-1][jj-1]+1;
elsedp[ii][jj] = max(dp[ii-1][jj],dp[ii][jj-1]);

3.dp数组的初始化。我们令所有第一行和第一列的元素全为0,表示,下标0到下标-1的元素最长公共子序列长度为0,便于进行元素的递推。
4.遍历顺序,先遍历text1或者先遍历text2都可以。

代码

class Solution {
public:int minDistance(string word1, string word2) {vector<vector<int>>dp(word1.size()+1,vector<int>(word2.size()+1,0));int result = 0;for(int ii =1;ii<word1.size()+1;ii++){for(int jj =1;jj<word2.size()+1;jj++){if(word1[ii-1]==word2[jj-1]) {dp[ii][jj] = dp[ii-1][jj-1]+1;result = max(result,dp[ii][jj]);}else dp[ii][jj] = max(dp[ii-1][jj],dp[ii][jj-1]);}}return word1.size()+word2.size()-2*result;}
};

思路2–直接动态规划

对于思路2,我们可以定义dp数组的含义为截止到word1[ii-1]与word2[jj-1]使得两个字符串相等所需要删除的最少元素个数。

因此,对于word1和word2中的元素有两种情况。
1.word1[ii-1]与word2[jj-1]相等,那么我们可以得到dp[ii][jj]应该与dp[ii-1][jj-1]相等,因为word1[ii-1]与word2[jj-1]相等,所以截止到word1[ii-1]与word2[jj-1]删除的元素应该与各个字符串前一个元素删除的元素个数相同。
2.word1[ii-1]与word2[jj-1]不相等,那么,我们可以得到由dp[ii-1][jj]和dp[ii][jj-1]得到,即要不删除word1一个元素,要不删除word2一个元素,这样就会得到dp[ii][jj].
即我们应该取他们之间的最小值dp[ii][jj] = min(dp[ii-1][jj]+1,dp[ii][jj-1]+1);

我们接下来用动态规划四部曲进行分析。
1.dp数组的含义。dp[ii][jj]表示截止到word1[ii-1]与word2[jj-1]使得两个字符串相等所需要删除的最少元素个数。
2.dp数组的递推公式。

if(word1[ii-1]==word2[jj-1]) dp[ii][jj] = dp[ii-1][jj-1];
else dp[ii][jj] = min(dp[ii-1][jj]+1,dp[ii][jj-1]+1);

3.dp数组的初始化。
显然对于dp数组任何一个数组为空时,我们都需要让另一个数组为空,才能让两个数组相等,因此,我们令第一列和第一行等于各自的下标。

        for(int ii =0;ii<word1.size()+1;ii++)dp[ii][0] = ii;for(int jj =0;jj<word2.size()+1;jj++)dp[0][jj] = jj;

4.dp数组的遍历顺序。先遍历word1和word2都可以。

代码

class Solution {
public:int minDistance(string word1, string word2) {vector<vector<int>>dp(word1.size()+1,vector<int>(word2.size()+1,0));for(int ii =0;ii<word1.size()+1;ii++)dp[ii][0] = ii;for(int jj =0;jj<word2.size()+1;jj++)dp[0][jj] = jj;for(int ii =1;ii<word1.size()+1;ii++){for(int jj =1;jj<word2.size()+1;jj++){if(word1[ii-1]==word2[jj-1]) dp[ii][jj] = dp[ii-1][jj-1];elsedp[ii][jj] = min(dp[ii-1][jj]+1,dp[ii][jj-1]+1);}}return dp[word1.size()][word2.size()];}
};

72.编辑距离

对于编辑距离,我们依旧用动态规划的思路来做。
我们定义dp数组的含义为dp[ii][jj]表示以word1[ii-1]结尾和以word2[jj-1]结尾的字符串所需要的最少操作数。

对于两个字符串中的元素,有两种结果,要么相等,要么不相等,因此我们分两种情况进行讨论。
1.如果word1[ii-1]与word2[jj-1]相同,那么我们要获得dp[ii][jj]只需要让dp[ii][jj]等于dp[ii-1][jj-1]即可,因为最后一个元素不用操作,只要前面的元素相同即可。
2.如果word1[ii-1]与word2[jj-1]不相同,那么我们可以对其进行增加、删除或者替换,而增加和删除可以被视为一种运算,因为对一个数组进行添加操作时相当于对另一个元素进行删除操作,所以我们统一视为删除操作。
如果是删除操作,我们可以删除word1中当前访问的元素或者删除word2中当前访问的元素。因此,可以得到dp[ii][jj] = min(dp[ii-1][jj],dp[ii][jj-1])+1;
如果是替换元素,那么我们将最后一个元素替换为另一个字符串中的元素,也就是令dp[ii][jj] = dp[ii-1][jj-1]+1;
因此如果是想要获得最少操作数,我们只需从中取得最小的操作数即可。
dp[ii][jj] = min(dp[ii-1][jj-1],min(dp[ii-1][jj],dp[ii][jj-1]))+1;

动态规划四部曲
1.dp数组的含义。dp数组的含义为dp[ii][jj]表示以word1[ii-1]结尾和以word2[jj-1]结尾的字符串所需要的最少操作数。
2.dp数组的推导公式。

 if(word1[ii-1]==word2[jj-1])    dp[ii][jj] = dp[ii-1][jj-1];
else    dp[ii][jj] = min(dp[ii-1][jj-1],min(dp[ii-1][jj],dp[ii][jj-1]))+1;

3.dp数组的遍历顺序。我们先对word1或者word2遍历都可以。
4.dp数组的初始化。同删除操作一样。我们如果让一个空数组与另一个数组相同时,都需要下标的操作数。即

        for(int ii =0;ii<word1.size()+1;ii++)dp[ii][0] = ii;for(int jj =0;jj<word2.size()+1;jj++)dp[0][jj] = jj;

代码

class Solution {
public:int minDistance(string word1, string word2) {vector<vector<int>>dp(word1.size()+1,vector<int>(word2.size()+1,0));for(int ii =0;ii<word1.size()+1;ii++)dp[ii][0] = ii;for(int jj =0;jj<word2.size()+1;jj++)dp[0][jj] = jj;for(int ii =1;ii<word1.size()+1;ii++)for(int jj =1;jj<word2.size()+1;jj++)if(word1[ii-1]==word2[jj-1])    dp[ii][jj] = dp[ii-1][jj-1];else    dp[ii][jj] = min(dp[ii-1][jj-1],min(dp[ii-1][jj],dp[ii][jj-1]))+1;return dp[word1.size()][word2.size()];}
};

http://www.ppmy.cn/news/44767.html

相关文章

Vue学习笔记(4. 生命周期)

1. 生命周期写法&#xff08;vue2与vue3比对&#xff09; 创建前&#xff1a;vue3 setup, vue2 beforeCreate //组件创建前执行的函数 创建后&#xff1a;vue3 setup, vue2 created //组件创建后执行的函数 挂载前&#xff1a;vue3 onBeforeMount, vue2 beforeMount //挂…

算法时间复杂度计算

目录 1.时间复杂度计算 1.1 时间复杂度例题 1.1.1例题 1.1.2例题 1.1.3例题 1.1.4例题 1.2时间复杂度leetcode例题 1.时间复杂度计算 首先&#xff0c;我们需要了解时间复杂度是什么&#xff1a;算法的时间复杂度是指算法在编写成可执行程序后&#xff0c;运行时需要耗费…

Java Menu

基本数据类型 Read More 【待重构】java,ruby,mysql 数据类型 运算符 对照学习笔记 和 equals 区别是什么&#xff1f; hashCode() 和 equals() 的关系List.equals和CollectionUtils.isEqualCollection的区别equals、Objects.equals、Objects.deepEquals区别和联系 Java三大特性…

MATLAB 不同格式点云文件的读取与显示(1)

不同格式的点云文件读取与显示(1) 一、背景介绍1.点云数据结构2.文件格式介绍2.1.ply文件2.2.pcd文件2.3.las文件2.4.txt文件二、不同格式文件读取与显示1.ply格式文件2.pcd格式文件3.txt格式文件三、其他操作1.修改显示背景色2.添加图例的显示3.improtdata(teapot.txt)报错一…

联诚发携多款创新产品及解决方案惊艳亮相ISLE 2023展!

这里写自定义目录标题4月7日-9日&#xff0c;ISLE 2023国际智慧显示及系统集成展览会在深圳国际会展中心&#xff08;宝安新馆&#xff09;隆重举行。来自全球各地1000余家企业参与展出&#xff0c;展出面积达8万㎡&#xff0c;吸引了众多业内专家、企业家以及广大观众前来观看…

API 接口应该如何设计?如何保证安全?如何签名?如何防重?

说明&#xff1a;在实际的业务中&#xff0c;难免会跟第三方系统进行数据的交互与传递&#xff0c;那么如何保证数据在传输过程中的安全呢&#xff08;防窃取&#xff09;&#xff1f;除了https的协议之外&#xff0c;能不能加上通用的一套算法以及规范来保证传输的安全性呢&am…

电子招标采购系统:营造全面规范安全的电子招投标环境,促进招投标市场健康可持续发展

营造全面规范安全的电子招投标环境&#xff0c;促进招投标市场健康可持续发展 传统采购模式面临的挑战 一、立项管理 1、招标立项申请 功能点&#xff1a;招标类项目立项申请入口&#xff0c;用户可以保存为草稿&#xff0c;提交。 2、非招标立项申请 功能点&#xff1a;非招标…

ubuntu_修改libc.so.6 或者 libm.so.6的软链接导致sudo ls 等命令失效的解决方法

1. 背景 运行一个binary 应用程序, 提示报错: /lib/x86_64-linux-gnu/libm.so.6: version GLIBC_2.27 not found (required by 我的应用程序string 里一下符号标, 确实没有然后下载了一个 glibc-2.27, 安装到 usr/local/下, 并将 libm-2.27.so 和 libc-2.27.so 复制到 /lib/x8…