【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 ...
随机推荐
- [转帖]CoreDump设置方式
https://www.jianshu.com/p/f5c3134072d2 本文讲述利用coredump调试时,对coredump信息相关的设置方式. 设置core文件大小 列出所有资源的限制 #u ...
- 感受 Vue3 的魔法力量
作者:京东科技 牛至伟 近半年有幸参与了一个创新项目,由于没有任何历史包袱,所以选择了Vue3技术栈,总体来说感受如下: • setup语法糖<script setup lang=" ...
- fbx查看软件
对于3D的模型资源,比如fbx文件,除了使用专业的软件查看外,比如Unity3D,vs2015及更高版本,maya,3DMax等等,有没有更加轻量的软件可以查看fbx的内容呢? win10自带 win ...
- postman测试Integer[]数组
背景说明:在做批量删除列表数据的时候,前端发送数组格式给后端,后端使用数组格式(Integer[] ids)接受,需要使用postman测试结果. @ApiOperation("管理系统-删 ...
- MongoDB 选型介绍
什么是 MongoDB 前言 MongoDB 的主要特性 MongoDB 对比关系型数据库 MySQL 什么时候考虑 MongoDB 参考 什么是 MongoDB 前言 MongoDB 是一个开源.高 ...
- border多层渐变
.content { margin-top: 19px; border-top: 1px dashed rgba(113, 183, 248, 0.6) !important; border-left ...
- Mac 下安装 mysqlclient
brew install mysql export LDFLAGS="-L/usr/local/opt/openssl/lib" export CPPFLAGS="-I/ ...
- 打开PDB报错ORA-30013
多租户架构,之前还在做运维的时期接触也不多.遇到多租户问题,第一反应是有些发虚的. 但实际很多问题很简单,也容易解决.本文就是一个例子. 问题:RAC节点2打开所有PDB时,报错ORA-30013. ...
- Delphi - Case 可以多条件 指定在一起,今天才知道;逗号分隔
- MySQL-生成随机数字、字符串、日期、验证码及 UUID的方法
一.生成随机数字 1. 生成 0 到 1 之间的随机数 MySQL 中的 RAND 函数可以用于生成一个大于等于 0 小于 1 的随机数字.例如: SELECT rand(); 该函数返回的数据类型为 ...