【动态规划】【字符串】1092. 最短公共超序列

作者推荐

【动态规划】【前缀和】【C++算法】LCP 57. 打地鼠

本文涉及知识点

动态规划汇总

LeetCode1092最短公共超序列

给你两个字符串 str1 和 str2,返回同时以 str1 和 str2 作为 子序列 的最短字符串。如果答案不止一个,则可以返回满足条件的 任意一个 答案。
如果从字符串 t 中删除一些字符(也可能不删除),可以得到字符串 s ,那么 s 就是 t 的一个子序列。
示例 1:
输入:str1 = “abac”, str2 = “cab”
输出:“cabac”
解释:
str1 = “abac” 是 “cabac” 的一个子串,因为我们可以删去 “cabac” 的第一个 "c"得到 “abac”。
str2 = “cab” 是 “cabac” 的一个子串,因为我们可以删去 “cabac” 末尾的 “ac” 得到 “cab”。
最终我们给出的答案是满足上述属性的最短字符串。
示例 2:
输入:str1 = “aaaaaaaa”, str2 = “aaaaaaaa”
输出:“aaaaaaaa”
提示:
1 <= str1.length, str2.length <= 1000
str1 和 str2 都由小写英文字母组成。

动态规划

原理

超串一定以str1.back或str2.back结尾 。

动态规划的状态表示

dp[i][j][use]=x,表示str1[0,i)和str2[0,j)的最短超串长度。use的含义如下:
{ 此超串的末尾已经匹配了 s t r 1 , s t r 2 3 此超串末尾匹配了 s t r 1 1 此超串末尾匹配了 s t r 2 2 \begin{cases} 此超串的末尾已经匹配了str1,str2 & 3 \\ 此超串末尾匹配了str1 & 1 \\ 此超串末尾匹配了str2 & 2 \end{cases} 此超串的末尾已经匹配了str1,str2此超串末尾匹配了str1此超串末尾匹配了str2312

动态规划的转移方程

dp[i][j][use] 更新dp[i+1][j][use1] preCh = (1&use) ? str1[i-1] : str2[j-1]。const int use1 = bNew ? 1 : (1 | use);
{ d p [ i + 1 ] [ j ] [ u s e 1 ] = m i n ( , d p [ i ] [ j ] [ u s e ] + 1 ) ( p r e C h ! = s t r 1 [ i ] ) 或 ( 1 位与 u s e ) d p [ i + 1 ] [ j ] [ u s e 1 ] = m i n ( , d p [ i ] [ j ] [ u s e ] ) e l s e \begin{cases} dp[i+1][j][use1] = min(,dp[i][j][use]+1) & (preCh!=str1[i])或(1位与use) \\ dp[i+1][j][use1] = min(,dp[i][j][use]) & else \\ \end{cases} {dp[i+1][j][use1]=min(,dp[i][j][use]+1)dp[i+1][j][use1]=min(,dp[i][j][use])(preCh!=str1[i])(1位与use)else
更新dp[i][j+1] [use1]类似

动态规划的填表顺序

I+j之和从1到大处理,use 从1到3,这样可以保证动态规划的无后效性。

动态规划的初始值

dp[1][0][1] =1;
dp[0][1][2] = 1;
其它dp 的值INT_MAX/2

动态规划的返回值

根据dp2 逆序组装。

代码

核心代码

class Solution {
public:string shortestCommonSupersequence(string str1, string str2) {m_r = str1.length();m_c = str2.length();vector<vector<vector<int>>> dp(m_r + 1, vector<vector<int>>(m_c + 1,vector<int>(4, INT_MAX / 2)));dp[1][0][1] =1;		dp[0][1][2] = 1;for (int len = 1; len < m_r + m_c; len++){for (int len1 = max(0,len-m_c); len1 <= min(len, m_r); len1++){const int len2 = len - len1;for (int use = 1; use <= 3; use++){const int preLen = dp[len1][len2][use];if (preLen >= INT_MAX / 2){continue;}const char preCh = (1 & use) ? str1[len1 - 1] : str2[len2 - 1];if (len1 < m_r){bool bNew = (preCh != str1[len1]) || (1 & use );const int use1 = bNew ? 1 : (1 | use);const int iNewLen = preLen + bNew;dp[len1 + 1][len2][use1] = min(dp[len1 + 1][len2][use1], iNewLen);		}if (len2 < m_c){bool bNew = (preCh != str2[len2]) || (2 & use );const int use1 = bNew ? 2 : (2 | use);const int iNewLen = preLen + bNew;dp[len1 ][len2 + 1][use1] = min(dp[len1][len2 + 1][use1], iNewLen);}}				}}string strRet;for (int len1 = m_r, len2 = m_c; len1 + len2 > 0; ){int use = std::min_element(dp[len1][len2].begin(), dp[len1][len2].end()) - dp[len1][len2].begin();const char preCh = (1 & use) ? str1[len1 - 1] : str2[len2 - 1];strRet += preCh;if (1 & use ){len1--;}if (2 & use ){len2--;}}std::reverse(strRet.begin(), strRet.end());return strRet;}int m_r, m_c;
};

测试用例

template<class T>
void Assert(const T& t1, const T& t2)
{assert(t1 == t2);
}template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{if (v1.size() != v2.size()){assert(false);return;}for (int i = 0; i < v1.size(); i++){Assert(v1[i], v2[i]);}}int main()
{	string str1,str2;{Solution sln;str1 = "abac", str2 = "cab";auto res = sln.shortestCommonSupersequence(str1, str2);assert(-1 != res.find(str1));assert(-2 != res.find(str1));Assert((int)res.length(),5 );}{Solution sln;str1 = "aaaaaaaa", str2 = "aaaaaaaa";auto res = sln.shortestCommonSupersequence(str1, str2);assert(-1 != res.find(str1));assert(-2 != res.find(str1));Assert(res.length(), string("aaaaaaaa").length());}
}

2023年1月版

先求最长公共子序列。
如果str1[i]==str2[j], 则一个字符匹配两个串。
否则比较dp[i-1][j] 和dp[i][j-1],采用公共子序列大的。

class Solution {
public:
string shortestCommonSupersequence(string str1, string str2) {
vector<vector> dp;
{
dp.assign(str1.length() + 1, vector(str2.length() + 1));
for (int i = 1; i <= str1.length(); i++)
{
for (int j = 1; j <= str2.length(); j++)
{
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
if (str1[i-1] == str2[j-1])
{
dp[i][j] = max(dp[i][j],dp[i - 1][j - 1] + 1);
}
}
}
}
string str;
int i = str1.length();
int j = str2.length();
str1 = " " + str1;
str2 = " " + str2;
while (i > 0 || j > 0)
{
if (0 == i)
{
str += str2[j–];
}
else if (0 == j)
{
str += str1[i–];
}
else if (str1[i] == str2[j])
{
str += str1[i];
i–, j–;
}
else
{
if (dp[i - 1][j] == dp[i][j])
{
str += str1[i–];
}
else
{
str += str2[j–];
}
}
}
return std::string(str.rbegin(), str.rend());
}
};

2023年8月版

class Solution {
public:
string shortestCommonSupersequence(string str1, string str2) {
m_c1 = str1.length();
m_c2 = str2.length();
vector<vector> dp(m_c1, vector(m_c2));
vector < vector<pair<int, int>>> vPre(m_c1, vector<pair<int, int>>(m_c2,std::make_pair<>(-1,-1)));
dp[0][0] = str1[0] == str2[0];
if (0 == dp[0][0])
{
vPre[0][0] = std::make_pair(0, -1);
}
for (int j = 1; j < m_c2; j++)
{
if (str1[0] == str2[j])
{
dp[0][j] = 1;
vPre[0][j] = std::make_pair(-1, j - 1);
}
else
{
dp[0][j] = dp[0][j - 1];
vPre[0][j] = std::make_pair(0, j - 1);
}
}
for (int i = 1; i < m_c1; i++)
{
if (str1[i] == str2[0])
{
dp[i][0] = 1;
vPre[i][0] = std::make_pair(i - 1, -1);
}
else
{
dp[i][0] = dp[i-1][0];
vPre[i][0] = std::make_pair(i-1,0);
}
}
for (int i = 1; i < m_c1; i++)
{
for (int j = 1; j < m_c2; j++)
{
if (str1[i] == str2[j])
{
dp[i][j] = 1 + dp[i - 1][j - 1];
vPre[i][j] = std::make_pair(i - 1, j - 1);
continue;
}
if (dp[i - 1][j] > dp[i][j - 1])
{
dp[i][j] = dp[i - 1][j];
vPre[i][j] = std::make_pair(i - 1, j);
}
else
{
dp[i][j] = dp[i ][j - 1];
vPre[i][j] = std::make_pair(i , j - 1);
}
}
}
int iNum = dp.back().back();
vector vRet;
auto it = std::make_pair(m_c1-1,m_c2-1);
for ( 😭-1 != it.first) && (-1 != it.second)😉
{
auto pre = vPre[it.first][it.second];
if (it.first != pre.first)
{
vRet.emplace_back(str1[it.first]);
}
else
{
vRet.emplace_back(str2[it.second]);
}
it = pre;
}
for (int i = it.first; i >= 0; i–)
{
vRet.emplace_back(str1[i]);
}
for (int i = it.second; i >= 0; i–)
{
vRet.emplace_back(str2[i]);
}
std::reverse(vRet.begin(), vRet.end());
vRet.emplace_back(0);
return vRet.data();
}
int m_c1, m_c2;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

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

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

相关文章

redis-sentinel(哨兵模式)

目录 1、哨兵简介:Redis Sentinel 2、作用 3、工作模式 4、主观下线和客观下线 5、配置哨兵模式 希望能够帮助到大家&#xff01;&#xff01;&#xff01; 1、哨兵简介:Redis Sentinel Sentinel(哨兵)是用于监控redis集群中Master状态的工具&#xff0c;其已经被集成在re…

【MySQL】数据库基础 -- 详解

一、什么是数据库 存储数据用文件就可以了&#xff0c;为什么还要弄个数据库? 一般的文件确实提供了数据的存储功能&#xff0c;但是文件并没有提供非常好的数据&#xff08;内容&#xff09;的管理能力&#xff08;用户角度&#xff09;。 文件保存数据有以下几个缺点&…

证明之黄金分割比的无理性

黄金分割比的无理性 “黄金分割比的神奇之处&#xff1a;视觉化证明与数学的魅力” 人们在学习高等数学时&#xff0c;走到一个证明的结尾处&#xff0c;通常会经历这样的思考&#xff1a;“我理解每一行是怎样由前一行得到的&#xff0c;但是我却不明白为什么这个定理是正确…

DS:顺序栈的实现

创作不易&#xff0c;友友们给个三连吧&#xff01;&#xff01; 一、栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先…

[神奇代码岛】皮肤功能使用

前言 最近有很多人在制作地图的时候&#xff0c;因该会用到皮肤的功能&#xff0c;但是皮肤操作只知道UI操作&#xff0c;但缺点是&#xff0c;只能设置地图默认皮肤&#xff0c;根本都做不到想要的什么皮肤购买功能&#xff0c;自主穿戴功能&#xff0c;而API官方又放在非常隐…

python爬虫入门(一)

使用requests 库获取网站html信息 import requests response requests.get("https://jingyan.baidu.com/article/17bd8e52c76b2bc5ab2bb8a2.html#:~:text1.%E6%89%93%E5%BC%80%E6%B5%8F%E8%A7%88%E5%99%A8F12%202.%E6%89%BE%E5%88%B0headers%E9%87%8C%E9%9D%A2%E7%9A%84…

【C++】初识模板:函数模板和类模板

目录 一、模板函数 1、函数模板的概念 2、函数模板的格式 3、函数模板的原理 4、函数模板实例化 5、 模板参数的匹配原则 二、类模板 1 、类模板的定义格式 2 、类模板的实例化 3、模板类示例 一、模板函数 1、函数模板的概念 函数模板代表了一个函数家族&#xff0c…

2024年安全员-B证证模拟考试题库及安全员-B证理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年安全员-B证证模拟考试题库及安全员-B证理论考试试题是由安全生产模拟考试一点通提供&#xff0c;安全员-B证证模拟考试题库是根据安全员-B证最新版教材&#xff0c;安全员-B证大纲整理而成&#xff08;含2024年…

比较6*6范围内7个点182个结构的顺序

( A, B )---6*30*2---( 1, 0 )( 0, 1 ) 让网络的输入有6个节点&#xff0c;训练集AB各由6张二值化的图片组成&#xff0c;让A中有7个点&#xff0c;让B全是0&#xff0c;收敛误差7e-4&#xff0c;收敛199次&#xff0c;统计迭代次数平均值并排序。 得到顺序为 用6个点的结构标…

【Godot4.2】图片处理函数库 - textureDB

概述 Godot中节点使用的图片是Texture2D或其子类型&#xff0c;而涉及图片处理&#xff0c;大多数功能在Image类型中&#xff0c;并且我们通常需要频繁的构造Image和ImageTexture类型。 为了封装构造Image和ImageTexture类型的代码&#xff0c;提供直接从文件到直接可以赋值给…

python 基础知识点(蓝桥杯python科目个人复习计划36)

今日复习计划&#xff1a;DFS搜索基础 1.简介 搜索方法&#xff1a;穷举问题解空间部分&#xff08;所有情况&#xff09;&#xff0c;从而求出问题的解。 深度优先搜索&#xff1a;本质上是暴力枚举 深度优先&#xff1a;尽可能一条路走到底&#xff0c;走不了再回退。 2…

《零基础实践深度学习》波士顿房价预测任务 02

1.3 波士顿房价预测任务 上一节我们初步认识了神经网络的基本概念&#xff08;如神经元、多层连接、前向计算、计算图&#xff09;和模型结构三要素&#xff08;模型假设、评价函数和优化算法&#xff09;。本节将以“波士顿房价预测”任务为例&#xff0c;向读者介绍使用Pytho…

C#在设备数据采集中的应用

设备数据采集在现代工业生产中扮演着至关重要的角色。随着工业互联网的发展&#xff0c;设备数据采集技术已经成为了智能制造的基础之一。在这篇文章中&#xff0c;我们将探讨C#语言在设备数据采集中的应用。 首先&#xff0c;让我们来了解一下设备数据采集的概念。设备数据采集…

购物|电商购物小程序|基于微信小程序的购物系统设计与实现(源码+数据库+文档)

电商购物小程序目录 目录 基于微信小程序的购物系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户前台功能实现 2、管理员后台功能实现 四、数据库设计 1、实体ER图 2、具体的表设计如下所示&#xff1a; 五、核心代码 六、论文参考 七、最新计算机毕设…

使用SpringMVC实现功能

目录 一、计算器 1、前端页面 2、服务器处理请求 3、效果 二、用户登陆系统 1、前端页面 &#xff08;1&#xff09;登陆页面 &#xff08;2&#xff09;欢迎页面 2、前端页面发送请求--服务器处理请求 3、效果 三、留言板 1、前端页面 2、前端页面发送请求 &…

day45_maven_tomcat

今日内容 0 复习昨日 1 maven 2 tomcat 3 创建项目 0 复习昨日 1 单词写5遍 argument 参数 parameter 参数 access 访问 field 字段 invoke 调用 illegal 非法 invalid 无效 column 列 property 属性 DataSource 数据源 2 数据库连接池有啥好处 3 获得字节码文件的方式 Class.f…

如何从 Windows 硬盘恢复丢失或删除的照片

您是否曾经不小心删除了无法再恢复的重要照片&#xff1f;如果这是您的商务或家庭照片、婚礼或童年回忆或者亲人的照片怎么办&#xff1f; 根据我们的经验&#xff0c;用户在清理计算机以提高存储/速度时通常会遇到此类事故&#xff0c;并最终删除包含重要图片的文件夹&#x…

VUE基础知识八 ElemrntUI使用

使用VUE脚手架以及在项目里引入ElementUI&#xff0c;上一章节讲过了&#xff0c;本章节就不赘述了。 ElementUI官网 所有使用ElementUI的组件&#xff0c;在使用时&#xff0c;都是以el-组件名开头的 一 按钮组件 ElementUI里的组件都是类似的&#xff0c;这里以按钮组件来…

AWD-Test2

1.已知账号密码&#xff0c;可SSH连接进行代码审计。2.登录可万能密码进入&#xff0c;也可注册后登录。3.修改url参数&#xff0c;发现报错。确定为Linux系统4.写入一句话&#xff0c;并提交。&#xff08;也可以文件上传&#xff0c;这里采用简洁的方法&#xff09; <?p…

macbookair怎么清理内存 ?如何利用 CleanMyMac X 进行系统清理

macbookair怎么清理内存 清理MacBook Air的内存可以通过以下几种方法&#xff1a; 优化储存空间。在MacBook Air上&#xff0c;可以通过“优化储存空间”来释放空间。这包括将文件储存在iCloud中&#xff0c;如桌面、文稿和iCloud信息&#xff0c;以及自动移除在iCloud中观看…