【LeetCode动态规划#15】最长公共子序列II
最长公共子序列(二)
描述
给定两个字符串str1和str2,输出两个字符串的最长公共子序列。如果最长公共子序列为空,则返回"-1"。目前给出的数据,仅仅会存在一个最长的公共子序列
数据范围:0≤∣���1∣,∣���2∣≤20000≤∣str1∣,∣str2∣≤2000
要求:空间复杂度 �(�2)O(n2) ,时间复杂度 �(�2)O(n2)
示例1
输入:
"1A2C3D4B56","B1D23A456A"
返回值:
"123456"
示例2
输入:
"abc","def"
返回值:
"-1"
示例3
输入:
"abc","abc"
返回值:
"abc"
示例4
输入:
"ab",""
返回值:
"-1"
思路
与最长重复子数组确定dp数组含义的思路类似,本题dp数组的含义是:s1的前i个字符与s2的前j个字符的最长公共子序列的长度
当s1遍历到i - 1,s2遍历到j - 1时最长公共子序列的长度为
dp[i][j]
然后使用两个指针i、j分别遍历两个字符串,
如果当前遍历值相等,那么当前位置的最长公共子序列长度一定可以由上一个位置的最长公共子序列长度加1得到;
如果当前遍历值不相等,则分别让i和j回退一位,取可以使dp数组更大的那个情况作为dp数组的更新值;
每次循环后,更新当前的dp数组的最大值到res
计算完毕dp数组后,根据dp数组去遍历s1、s2来获得输出字符串out
具体实现步骤如下:
- 初始化一个空字符串
out,用于存储最长公共子序列。- 根据动态规划的思想,从右下角开始向左上角遍历dp数组。变量
i和j分别表示当前遍历的位置。- 如果
s1[i - 1]等于s2[j - 1],说明当前字符是公共字符,将它添加到out的前面,并将i和j都向左上方移动一位。- 如果不相等,则比较
dp[i - 1][j]和dp[i][j - 1]的大小,选择较大的方向移动。如果二者相等,则优先向左移动。- 重复步骤3和步骤4,直到
i或j为0。- 返回最终得到的
out字符串,即为最长公共子序列。
代码
#include <vector>
class Solution {
public:
string LCS(string s1, string s2) {
vector<vector<int>> dp(s1.size() + 1, vector<int>(s2.size() + 1, 0));
int res = 0;
for (int i = 1; i <= s1.size(); ++i) {
for (int j = 1; j <= s2.size(); ++j) {
if (s1[i - 1] == s2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
if (dp[i][j] > res) {
res = dp[i][j];
}
}
}
if (res == 0)
return "-1";
string out = "";
int i = s1.size();
int j = s2.size();
while (i > 0 && j > 0) {
if (s1[i - 1] == s2[j - 1]) {
out = s1[i - 1] + out;
i--;
j--;
} else if (dp[i - 1][j] >= dp[i][j - 1]) {
i--;
} else {
j--;
}
}
return out;
}
};
往dp数组值较大的方向移动是为了确保选择的路径上能够包含更多的公共字符,从而得到最长的公共子序列。
举个例子来说明计算得到的dp数组的形状:
假设s1 = "ABCBDAB"和s2 = "BDCAB",则dp数组的形状如下所示:
B D C A B
A 0 0 0 1 1
B 1 1 1 1 2
C 1 1 2 2 2
B 1 1 2 2 3
D 1 2 2 2 3
A 1 2 2 3 3
B 1 2 2 3 4
dp[i][j]表示s1的前i个字符与s2的前j个字符的最长公共子序列的长度。根据题目要求,我们希望得到最长的公共子序列,因此,在遍历时如果当前字符相等,就选择左上方对角线上的值加1,表示当前字符也属于公共子序列;如果不相等,则选择左方或上方较大的值,表示忽略当前字符。
在这个例子中,dp[7][5]的值为4,表示s1的前7个字符与s2的前5个字符的最长公共子序列的长度为4。通过回溯路径,我们可以得到最长公共子序列为"BCBA"。
在计算out字符串时,根据上述例子,从右下角开始,按照选择的方向移动,即可得到最长公共子序列"BCBA"。
【LeetCode动态规划#15】最长公共子序列II的更多相关文章
- 动态规划之最长公共子序列(LCS)
转自:http://segmentfault.com/blog/exploring/ LCS 问题描述 定义: 一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 ...
- 动态规划求最长公共子序列(Longest Common Subsequence, LCS)
1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...
- 动态规划之最长公共子序列LCS(Longest Common Subsequence)
一.问题描述 由于最长公共子序列LCS是一个比较经典的问题,主要是采用动态规划(DP)算法去实现,理论方面的讲述也非常详尽,本文重点是程序的实现部分,所以理论方面的解释主要看这篇博客:http://b ...
- 动态规划经典——最长公共子序列问题 (LCS)和最长公共子串问题
一.最长公共子序列问题(LCS问题) 给定两个字符串A和B,长度分别为m和n,要求找出它们最长的公共子序列,并返回其长度.例如: A = "HelloWorld" B = & ...
- HDU 1159 Common Subsequence (动态规划、最长公共子序列)
Common Subsequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other ...
- hdu1159Common Subsequence——动态规划(最长公共子序列(LCS))
Problem Description A subsequence of a given sequence is the given sequence with some elements (poss ...
- 【转】动态规划之最长公共子序列(LCS)
[原文链接]最长公共子序列(Longest Common Subsequence,简称 LCS)是一道非常经典的面试题目,因为它的解法是典型的二维动态规划,大部分比较困难的字符串问题都和这个问题一个套 ...
- uva111动态规划之最长公共子序列
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=74662#problem/C A B C D E C - Largest Rect ...
- 动态规划算法——最长公共子序列问题(java实现)
已知序列X=(A,B,C,A,B,D,A)和序列Y=(B,A,D,B,A),求它们的最长公共子序列S. /* * LCSLength.java * Version 1.0.0 * Created on ...
- Coincidence (动态规划求最长公共子序列)(王道)
题目描述: Find a longest common subsequence of two strings. 输入: First and second line of each input case ...
随机推荐
- [转帖]Linux中的Page cache和Buffer cache详解
1.内存情况 在讲解Linux内存管理时已经提到,当你在Linux下频繁存取文件后,即使系统上没有运行许多程序,也会占用大量的物理内存.这是因为当你读写文件的时候,Linux内核为了提高读写的性能和速 ...
- [转帖]CPU计算性能speccpu2006的测试方法及工具下载
https://www.yii666.com/blog/335517.html CPU计算性能speccpu2006的测试方法及工具下载 简介 测试原理 目录结构 测试方法 基准测试项解析 测试结果 ...
- Linux无头模式使用mat分析dump的方法
摘要 mat可以很好的进行jvm的内存dump的分析. 但是大部分服务器是没有GUI界面的. 而且就算是有GUI界面也很难直接使用. 但是随着jvm堆区越来越大. WindowsPC机器已经很难进行分 ...
- hover时行级元素变成了块级元素,导致位置错乱
在hover时,i元素变成了块级元素: 导致这两个元素各自占了一行: 最终导致样式错乱: <div class="demo"> <!-- 添加图标 和 编辑图标 ...
- 不同版本的Unity要求的NDK版本和两者对应关系表(Unity NDK Version Match)
IL2CPP需要NDK Unity使用IL2CPP模式出安卓包时,需要用到NDK,如果没有安装则无法导出Android Studio工程或直接生成APK,本篇记录一下我下载NDK不同版本的填坑过程. ...
- .NET MAUI 简介
欢迎使用.NET 多平台应用程序 UI.此版本标志着我们在统一 .NET 平台的多年旅程中的新里程碑.现在,您和超过 500 万其他 .NET 开发人员拥有面向 Android.iOS.macOS 和 ...
- 《重学Java设计模式》作者开始录视频了!
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 1. 前言 哈哈哈,终于对B站下手了! 大家好,我是小傅哥,在紧张.羞涩到适应后,哈哈哈,终于 ...
- DataSet类型转换实体
查询DataSet类型无法对每条数据进行循环转换,利用泛型对象使用反射机制将对象相关属性进行自动赋值. 基础调用 DataSet ds = DbHelper.Query(SQL); if (ds.Ta ...
- Python下的三维建模和可视化
本文介绍基于AnyCAD Rapid Py三维图形平台开发Python的三维应用 1 准备工作 1.1 安装 vc_resit 2022 在Windows下,AnyCAD Rapid SDK依赖Vis ...
- ElasticSearch7.3学习(三)----采用restful风格 批量(bulk)增删改
Bulk 操作是将文档的增删改查一些列操作,通过一次请求全都做完.目的是减少网络传输次数. 语法: POST /_bulk {"action": {"metadata&q ...