最长公共子序列(二)

描述

给定两个字符串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

具体实现步骤如下:

  1. 初始化一个空字符串out,用于存储最长公共子序列。
  2. 根据动态规划的思想,从右下角开始向左上角遍历dp数组。变量ij分别表示当前遍历的位置。
  3. 如果s1[i - 1]等于s2[j - 1],说明当前字符是公共字符,将它添加到out的前面,并将ij都向左上方移动一位。
  4. 如果不相等,则比较dp[i - 1][j]dp[i][j - 1]的大小,选择较大的方向移动。如果二者相等,则优先向左移动。
  5. 重复步骤3和步骤4,直到ij为0。
  6. 返回最终得到的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的更多相关文章

  1. 动态规划之最长公共子序列(LCS)

    转自:http://segmentfault.com/blog/exploring/ LCS 问题描述 定义: 一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 ...

  2. 动态规划求最长公共子序列(Longest Common Subsequence, LCS)

    1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...

  3. 动态规划之最长公共子序列LCS(Longest Common Subsequence)

    一.问题描述 由于最长公共子序列LCS是一个比较经典的问题,主要是采用动态规划(DP)算法去实现,理论方面的讲述也非常详尽,本文重点是程序的实现部分,所以理论方面的解释主要看这篇博客:http://b ...

  4. 动态规划经典——最长公共子序列问题 (LCS)和最长公共子串问题

    一.最长公共子序列问题(LCS问题) 给定两个字符串A和B,长度分别为m和n,要求找出它们最长的公共子序列,并返回其长度.例如: A = "HelloWorld"    B = & ...

  5. HDU 1159 Common Subsequence (动态规划、最长公共子序列)

    Common Subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  6. hdu1159Common Subsequence——动态规划(最长公共子序列(LCS))

    Problem Description A subsequence of a given sequence is the given sequence with some elements (poss ...

  7. 【转】动态规划之最长公共子序列(LCS)

    [原文链接]最长公共子序列(Longest Common Subsequence,简称 LCS)是一道非常经典的面试题目,因为它的解法是典型的二维动态规划,大部分比较困难的字符串问题都和这个问题一个套 ...

  8. uva111动态规划之最长公共子序列

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=74662#problem/C     A B C D E C - Largest Rect ...

  9. 动态规划算法——最长公共子序列问题(java实现)

    已知序列X=(A,B,C,A,B,D,A)和序列Y=(B,A,D,B,A),求它们的最长公共子序列S. /* * LCSLength.java * Version 1.0.0 * Created on ...

  10. Coincidence (动态规划求最长公共子序列)(王道)

    题目描述: Find a longest common subsequence of two strings. 输入: First and second line of each input case ...

随机推荐

  1. 我对computed的理解-以及computed的传参

    computed 传参 <template> <div> <p>computed传参的写法:{{ who1Params('--我是传参的内容') }}</p& ...

  2. 学到了,原来 gzip 是种`连续分块`的压缩算法

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 我想要表述的是:假设有 10 mb的数据使用 gzip 算 ...

  3. MySQL 列操作记录

    在 MySQL 中,你可以使用多种命令和语句来执行列操作,包括添加.修改.删除列等.以下是一些与列操作相关的常用 MySQL 命令和语句: 1. 添加列: 添加新列到表格中: ALTER TABLE ...

  4. Docker获取Let`s Encrypt SSL 证书

    文中的操作都是在CentOS Stream release 9下执行的,使用的是root用户. 1. 安装docker # 卸载原有的docker yum remove docker docker-c ...

  5. P5963 [BalticOI ?] Card 卡牌游戏【来源请求】

    [rt](https://www.luogu.com.cn/problem/P5963)------------## part1### 题意简述给你 $n$ 张纸牌,每张纸牌有两个面.将 $n$ 张纸 ...

  6. 从零开始配置vim(28)——DAP 配置

    首先给大家说一声抱歉,前段时间一直在忙换工作的事,包括但不限于交接.背面试题准备面试.好在最终找到了工作,也顺利入职了.期间也有朋友在催更,在这里我对关注本系列的朋友表示感谢.多的就不说了,我们正式进 ...

  7. 19.9 Boost Asio 同步字典传输

    这里所代指的字典是Python中的样子,本节内容我们将通过使用Boost中自带的Tokenizer分词器实现对特定字符串的切割功能,使用Boost Tokenizer,可以通过构建一个分隔符或正则表达 ...

  8. C/C++ 文件与指针操作笔记

    创建临时文件 #include <stdio.h> int main(int argc, char *argv[]) { FILE *temp; char c; if ((temp = t ...

  9. Windows 恶意软件数量是 Mac 的 5000 倍,是 Linux 的 36 倍

    AV-TEST 是一个独立的测试机构,他们会根据各种标准对操作系统的防病毒和安全软件进行评估和评级,并将测试结果免费提供给用户,帮助用户选择最适合自己的产品.近日,AV-TEST 联合旗下的威胁情报平 ...

  10. (转)时代的见证:集成更新的Windows 7旗舰版、专业版镜像

    制作缘起:微软曾于2019年提供过两份内部集成更新的英文旗舰版.专业版镜像(参见:集成IE11+最新补丁:微软新版Windows 7镜像泄露),方便用户安装,缩短更新过程.经我们下载安装研究发现,这两 ...