动态规划经典——最长公共子序列问题 (LCS)和最长公共子串问题
一.最长公共子序列问题(LCS问题)
给定两个字符串A和B,长度分别为m和n,要求找出它们最长的公共子序列,并返回其长度。例如:
A = "HelloWorld"
B = "loop"
则A与B的最长公共子序列为 "loo",返回的长度为3。此处只给出动态规划的解法:定义子问题dp[i][j]为字符串A的第一个字符到第 i 个字符串和字符串B的第一个字符到第 j 个字符的最长公共子序列,如A为“app”,B为“apple”,dp[2][3]表示 “ap” 和 “app” 的最长公共字串。注意到代码中 dp 的大小为 (n + 1) x (m + 1) ,这多出来的一行和一列是第 0 行和第 0 列,初始化为 0,表示空字符串和另一字符串的子串的最长公共子序列,例如dp[0][3]表示 "" 和 “app” 的最长公共子串。
class LCS
{
public:
int findLCS(string A, int n, string B, int m)
{
if(n == 0 || m == 0)//特殊输入
return 0;
int dp[n + 1][m + 1];//定义状态数组
for(int i = 0 ; i <= n; i++)//初始状态
dp[i][0] = 0;
for(int i = 0; i <= m; i++)
dp[0][i] = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j<= m; j++)
{
if(A[i - 1] == B[j - 1])//判断A的第i个字符和B的第j个字符是否相同
dp[i][j] = dp[i -1][j - 1] + 1;
else
dp[i][j] = max(dp[i - 1][j],dp[i][j - 1]);
}
return dp[n][m];//最终的返回结果就是dp[n][m]
}
};
该算法的时间复杂度为O(n*m),空间复杂度为O(n*m)。此外,由于遍历时是从下标1开始的,因为下标为0表示空字符串;所以第A的第i个字符实际上为A[i -1],B的第j个字符为B[j-1]。
二.最长公共子串问题
给定两个字符串A和B,长度分别为m和n,要求找出它们最长的公共子串,并返回其长度。例如:
A = "HelloWorld"
B = "loop"
则A与B的最长公共子串为 "lo",返回的长度为2。我们可以看到子序列和子串的区别:子序列和子串都是字符集合的子集,但是子序列不一定连续,但是子串一定是连续的。同样地,这里只给出动态规划的解法:定义dp[i][j]表示以A中第i个字符结尾的子串和B中第j个字符结尾的子串的的最大公共子串(公共子串实际上指的是这两个子串的所有部分)的长度(要注意这里和LCS的不同,LCS中的dp[i+1][j+1]一定是大于等于dp[i][j]的;但最长公共子串问题就不一定了,它的dp[i][j]表示的子串不一定是以A[0]开头B[0]开头的,但是一定是以A[i-1]、B[j-1]结尾的),同样地, dp 的大小也为 (n + 1) x (m + 1) ,这多出来的一行和一列是第 0 行和第 0 列,初始化为 0,表示空字符串和另一字符串的子串的最长公共子串。
当我们要求dp[i][j],我们要先判断A的第i个元素B的第j个元素是否相同即判断A[i - 1]和 B[j -1]是否相同,如果相同它就是dp[i - 1][j- 1] + 1,相当于在两个字符串都去掉一个字符时的最长公共子串再加 1;否则最长公共子串取0。所以整个问题的初始状态为:
$$ dp[i][0] =0 , dp[0][j] = 0$$
class LongestSubstring {
public:
int findLongest(string A, int n, string B, int m) {
if(n == 0 || m == 0)
return 0;
int rs = 0;
int dp[n + 1][m + 1];
for(int i = 0 ; i <= n; i++)//初始状态
dp[i][0] = 0;
for(int i = 0; i <= m; i++)
dp[0][i] = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j<= m; j++)
{
if(A[i - 1] == B[j - 1])
{
dp[i][j] = dp[i -1][j - 1] + 1;
rs = max(rs,dp[i][j]);//每次更新记录最大值
}
else//不相等的情况
dp[i][j] = 0;
}
return rs;//返回的结果为rs
}
};
该算法的时间复杂度为O(n*m),空间复杂度为O(n*m)。同样地,遍历下标也是从1开始的。不过关于最长公共子串问题,有几点需要注意下:
1.由于dp[i][j]不像LCS是个递增的数组,所以它在每次更新时需要同时更新最大值rs,且最后返回的结果是rs。而LCS中返回的直接就是dp[n][m]。
2.从代码上来看,两者的结构其实差不多,只不过状态转移方程有些小许的不同,分析过程也类似。
3.另外,关于这量两种问题还有更优的解法,不过本文主要是DP的思想去解决,当然其中还有对DP的优化,不过此处不再详述。
参考:https://www.nowcoder.com/questionTerminal/c996bbb77dd447d681ec6907ccfb488a
动态规划经典——最长公共子序列问题 (LCS)和最长公共子串问题的更多相关文章
- 最长递增子序列(lis)最长公共子序列(lcs) 最长公共上升子序列(lics)
lis: 复杂度nlgn #include<iostream> #include<cstdio> using namespace std; ],lis[],res=; int ...
- 最长公共子序列(LCS)最长递增子序列(LIS)
#include<cstring>#include<iostream>#include<stack>#include <algorithm>using ...
- 删除部分字符使其变成回文串问题——最长公共子序列(LCS)问题
先要搞明白:最长公共子串和最长公共子序列的区别. 最长公共子串(Longest Common Substirng):连续 最长公共子序列(Longest Common Subsequence,L ...
- 最长公共子序列(LCS问题)
先简单介绍下什么是最长公共子序列问题,其实问题很直白,假设两个序列X,Y,X的值是ACBDDCB,Y的值是BBDC,那么XY的最长公共子序列就是BDC.这里解决的问题就是需要一种算法可以快速的计算出这 ...
- 【Luogu P1439】最长公共子序列(LCS)
Luogu P1439 令f[i][j]表示a的前i个元素与b的前j个元素的最长公共子序列 可以得到状态转移方程: if (a[i]==b[j]) dp[i][j]=dp[i-1][j-1]+1; d ...
- 最长公共子序列(LCS)、最长递增子序列(LIS)、最长递增公共子序列(LICS)
最长公共子序列(LCS) [问题] 求两字符序列的最长公共字符子序列 问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字 ...
- nyoj 36 最长公共子序列【LCS模板】
最长公共子序列 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 咱们就不拐弯抹角了,如题,需要你做的就是写一个程序,得出最长公共子序列.tip:最长公共子序列也称作最 ...
- 最长公共子序列问题 (LCS)
给定两个字符串S和T.求出这两个字符串最长的公共子序列的长度. 输入: n=4 m=4 s="abcd" t="becd" 输出: 3("bcd&qu ...
- 动态规划法(十)最长公共子序列(LCS)问题
问题介绍 给定一个序列\(X=<x_1,x_2,....,x_m>\),另一个序列\(Z=<z_1,z_2,....,z_k>\)满足如下条件时称为X的子序列:存在一个严格 ...
随机推荐
- 通过class改变样式
1.判断class属性 判断一个元素中是否含有指定的class属性值 function hasClass(obj,cn){ //创建正则表达式 var reg=new RegExp("\\b ...
- xml字符串,xml对象,数组之间的相互转化
<?phpnamespace Home\Controller;use Think\Controller;class IndexController extends Controller { pu ...
- 布局神器 display:flex;
布局神器 display:flex; 2009年,W3C提出了一种新的方案--Flex布局,可以简便.完整.响应式地实现各种页面布局.目前已得到所有现在浏览器的支持. 一.Flex布局是什么? Fle ...
- ES6--闭包数组i的值与var的作用域理解
var a = [];for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); };}a[6](); // 10 变 ...
- Com 调用word和excel
using Microsoft.Office.Interop.Word;using System;using System.Collections.Generic;using System.Compo ...
- intelij idea模板
1.idea设置模板 Postfix Completion是无法改变的模板 live Template是可以修改的 自定义模板 如下图: 创建测试方法: $VAR1$代表光标占位符
- Sql语句内功心法
CREATE SCHEMA <模式名> AUTHORIZATION <用户名> 定义模式实际上定义了一个命名空间,在这个空间可以进一步定义该模式包含的数据库对象,例如基本表,视 ...
- 马凯军201771010116《面向对象程序设计(java)》第七周学习总结
理论与知识部分 多态性:概念:指在程序中同一符号在不同的情况下具有不同的解释.超类中定义的域或方法,被子类继承之后,可以具有不同的数据类型或表现出不同的行为.这使得同一域或方法在超类及各个子类中具有不 ...
- 邮件远控电脑MCC-python实现
本次实现的是一个通过邮件来远程控制电脑,以达到某些远程操作,例如让电脑执行CMD命令,播放音乐,打开指定文件等操作的项目.代码参考了网上的部分教程. 具体流程: 在python代码中,通过一个循环来接 ...
- 剑指Offer 10. 矩形覆盖 (递归)
题目描述 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形.请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 题目地址 https://www.nowcoder.com/ ...