最长公共子序列(二)

描述

给定两个字符串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. [转帖][译]ARM大小核架构白皮书

    https://zhuanlan.zhihu.com/p/33411449 ARM big.LITTLE Processing with ARM Cortex-A15 & Cortex-A7 ...

  2. 记一次JSF异步调用引起的接口可用率降低

    前言 本文记录了由于JSF异步调用超时引起的接口可用率降低问题的排查过程,主要介绍了排查思路和JSF异步调用的流程,希望可以帮助大家了解JSF的异步调用原理以及提供一些问题排查思路.本文分析的JSF源 ...

  3. 京东云开发者|深入JDK中的Optional

    概述:Optional最早是Google公司Guava中的概念,代表的是可选值.Optional类从Java8版本开始加入豪华套餐,主要为了解决程序中的NPE问题,从而使得更少的显式判空,防止代码污染 ...

  4. 强化学习从基础到进阶-常见问题和面试必知必答[4]::深度Q网络-DQN、double DQN、经验回放、rainbow、分布式DQN

    强化学习从基础到进阶-常见问题和面试必知必答[4]::深度Q网络-DQN.double DQN.经验回放.rainbow.分布式DQN 1.核心词汇 深度Q网络(deep Q-network,DQN) ...

  5. 一些提供办公效率的软件(clover、f.lux、幕布),老赞了!

    1.clover 链接:http://cn.ejie.me/ Clover是由异次元的读者ejie团队开发的一款电脑窗口标签化工具.Clover是电脑中资源管理器的一个扩展程序,可以为其增加多标签页的 ...

  6. 【7】vscode不同的窗口样式和颜色插件peacock、设置打开多个窗口、md文件打开方式和预览以及插入目录

    相关文章: [1]VScode中文界面方法-------超简单教程 [2]VScode搭建python和tensorflow环境 [3]VSCode 主题设置推荐,自定义配色方案,修改注释高亮颜色 [ ...

  7. 19.9 Boost Asio 同步字典传输

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

  8. C/C++ 监控磁盘与目录操作

    遍历磁盘容量: #include <stdio.h> #include <Windows.h> void GetDrivesType(const char* lpRootPat ...

  9. 该换Linux版本了!

    提起开发,程序员们更青睐于不同版本的Linux操作系统而不是Windows.为什么?因为Linux操作起来更安全.快捷,最重要的是,它的发行版本众多.你可以根据需要挑选最适合的那一款.那么,问题来了, ...

  10. electron 开发 ,如何使用 第三方 库 进行typescript 开发,举例:jquery 其它的 应该也是一致。

    首先要弄明白一点,electron 开发 与 nodejs开发 基本一致. 要引入 jquery 实际上就是 nodejs 引入 jquery 第一步是 去 nmp中央仓库,查看,里面有详细的说明使用 ...