1. 问题描述

子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串

  • cnblogs
  • belong

比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与母串保持一致,我们将其称为公共子序列。最长公共子序列(Longest Common Subsequence,LCS),顾名思义,是指在所有的子序列中最长的那一个。子串是要求更严格的一种子序列,要求在母串中连续地出现。在上述例子的中,最长公共子序列为blog(cnblogs,belong),最长公共子串为lo(cnblogs, belong)。

2. 求解算法

对于母串X=<x1,x2,⋯,xm>, Y=<y1,y2,⋯,yn>,求LCS与最长公共子串。
暴力解法
假设 m<n, 对于母串X,我们可以暴力找出2的m次方个子序列,然后依次在母串Y中匹配,算法的时间复杂度会达到指数级O(n∗2的m次)。显然,暴力求解不太适用于此类问题。
动态规划
假设Z=<z1,z2,⋯,zk>是X与Y的LCS, 我们观察到
如果Xm=Yn,则Zk=Xm=Yn,有Zk−1是Xm−1与Yn−1的LCS;
如果Xm≠Yn,则Zk是Xm与Yn−1的LCS,或者是Xm−1与Yn的LCS。
因此,求解LCS的问题则变成递归求解的两个子问题。但是,上述的递归求解的办法中,重复的子问题多,效率低下。改进的办法——用空间换时间,用数组保存中间状态,方便后面的计算。这就是动态规划(DP)的核心思想了。
DP求解LCS
用二维数组c[i][j]记录串x1x2⋯xi与y1y2⋯yj的LCS长度,则可得到状态转移方程

代码实现

 public static int lcs(String str1, String str2) {
int len1 = str1.length();
int len2 = str2.length();
int c[][] = new int[len1+][len2+];
for (int i = ; i <= len1; i++) {
for( int j = ; j <= len2; j++) {
if(i == || j == ) {
c[i][j] = ;
} else if (str1.charAt(i-) == str2.charAt(j-)) {
c[i][j] = c[i-][j-] + ;
} else {
c[i][j] = max(c[i - ][j], c[i][j - ]);
}
}
}
return c[len1][len2];
}

DP求解最长公共子串

前面提到了子串是一种特殊的子序列,因此同样可以用DP来解决。定义数组的存储含义对于后面推导转移方程显得尤为重要,糟糕的数组定义会导致异常繁杂的转移方程。考虑到子串的连续性,将二维数组c[i][j]用来记录具有这样特点的子串——结尾同时也为为串x1x2⋯xi与y1y2⋯yj的结尾——的长度。
得到转移方程:

最长公共子串的长度为 max(c[i,j]), i∈{1,⋯,m},j∈{1,⋯,n}。
代码实现

 public static int lcs(String str1, String str2) {
int len1 = str1.length();
int len2 = str2.length();
int result = ; //记录最长公共子串长度
int c[][] = new int[len1+][len2+];
for (int i = ; i <= len1; i++) {
for( int j = ; j <= len2; j++) {
if(i == || j == ) {
c[i][j] = ;
} else if (str1.charAt(i-) == str2.charAt(j-)) {
c[i][j] = c[i-][j-] + ;
result = max(c[i][j], result);
} else {
c[i][j] = ;
}
}
}
return result;
}

例题

pat-C4 L2-008  最长对称的回文串

 #include <bits/stdc++.h>
using namespace std;
const int N=1e3+;
char s1[N],s2[N];
int dp[N][N];
int main ()
{
gets (s1+); strcpy(s2+,s1+);
int len=strlen(s1+);
reverse(s2+, s2++len);
int ans=;
for (int i=;i<=len;i++)
for (int j=;j<=len;j++) {
if (i==||j==) dp[i][j]=;
else if (s1[i]==s2[j]) {
dp[i][j]=dp[i-][j-]+;
ans=max (ans,dp[i][j]);
}
else dp[i][j]=;
}
printf ("%d\n",ans);
return ;
}

最长公共子序列与最长公共字串 (dp)转载http://blog.csdn.net/u012102306/article/details/53184446的更多相关文章

  1. [Python]最长公共子序列 VS 最长公共子串[动态规划]

    前言 由于原微软开源的基于古老的perl语言的Rouge依赖环境实在难以搭建,遂跟着Rouge论文的描述自行实现. Rouge存在N.L.S.W.SU等几大子评估指标.在复现Rouge-L的函数时,便 ...

  2. hdu 1950 最长上升子序列(lis) nlogn算法【dp】

    这个博客说的已经很好了.http://blog.csdn.net/shuangde800/article/details/7474903 简单记录一下自己学的: 问题就是求一个数列最长上升子序列的长度 ...

  3. [Data Structure] LCSs——最长公共子序列和最长公共子串

    1. 什么是 LCSs? 什么是 LCSs? 好多博友看到这几个字母可能比较困惑,因为这是我自己对两个常见问题的统称,它们分别为最长公共子序列问题(Longest-Common-Subsequence ...

  4. 动态规划 最长公共子序列 LCS,最长单独递增子序列,最长公共子串

    LCS:给出两个序列S1和S2,求出的这两个序列的最大公共部分S3就是就是S1和S2的最长公共子序列了.公共部分 必须是以相同的顺序出现,但是不必要是连续的. 选出最长公共子序列.对于长度为n的序列, ...

  5. 【ZH奶酪】如何用Python计算最长公共子序列和最长公共子串

    1. 什么是最长公共子序列?什么是最长公共子串? 1.1. 最长公共子序列(Longest-Common-Subsequences,LCS) 最长公共子序列(Longest-Common-Subseq ...

  6. 用Python计算最长公共子序列和最长公共子串

    如何用Python计算最长公共子序列和最长公共子串 1. 什么是最长公共子序列?什么是最长公共子串? 1.1. 最长公共子序列(Longest-Common-Subsequences,LCS) 最长公 ...

  7. 动态规划1——最长递增子序列、最长公共子序列、最长公共子串(python实现)

    目录 1. 最长递增序列 2. 最长公共子序列 3. 最长公共子串 1. 最长递增序列 给定一个序列,找出其中最长的,严格递增的子序列的长度(不要求连续). 解法一:动态规划 通过一个辅助数组记录每一 ...

  8. O(n log n)求最长上升子序列与最长不下降子序列

    考虑dp(i)表示新上升子序列第i位数值的最小值.由于dp数组是单调的,所以对于每一个数,我们可以二分出它在dp数组中的位置,然后更新就可以了,最终的答案就是dp数组中第一个出现正无穷的位置. 代码非 ...

  9. 最长公共子序列PK最长公共子串

    1.先科普下最长公共子序列 & 最长公共子串的区别: 找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的.而最长公共子序列则并不要求连续. (1)递归方法求最长公共子序列的长度 1) ...

随机推荐

  1. Kali配置教程

    1.配置软件源 所有操作没有说明,都是以root身份执行. 打开一个终端执行: cat >> /etc/apt/sources.list <<EOF deb http://mi ...

  2. Easyui的datagrid的行编辑器Editor中添加事件(修改某个单元格带出其他单元格的值)

    项目中有个datagrid需要编辑行时,用到Editor的属性,那么如何添加一个事件 问题:同一个编辑行中的某个单元格值改变时,修改其他单元格的值 页面用到的datagrid <table id ...

  3. hash与平衡二叉树的区别

    哈希表的定义:哈希表是一种根据关键码去寻找值的数据映射结构,该结构通过把关键码映射的位置去寻找存放值的地方 https://blog.csdn.net/duan19920101/article/det ...

  4. 【HttpClient】一个http_post请求例子

    package httpclient.httpclient; import java.io.IOException; import org.apache.http.Header; import org ...

  5. Jenkins的安装、启动和配置

    一.Jenkins的安装 1.前提条件:已经成功安装了JDK,因为jenkins是一款基于Java的持续集成工具. 2.准备工具:下载一个jenkins的war包. 3.启动方法:如把jenkins. ...

  6. os 模块 和 os模块下的path模块

    import os # os 主要用于与操作系统进行交互 #获取当前的工作目录 print(os.getcwd()) #切换工作目录 os .chdir("D:\上海python全栈4期\d ...

  7. 基于iscroll的better-scroll在vue中的使用

    什么是 better-scroll better-scroll 是一个移动端滚动的解决方案,它是基于 iscroll 的重写,它和 iscroll 的主要区别在这里.better-scroll 也很强 ...

  8. xml的方式配置AOP:Aspect Oriented Programming

    在某些类中, 什么时机, 做什么事情 切入点(point-cut): 在某些类中(Class<?>[] itfc = new Class<?>[] { IStudentServ ...

  9. Win10访问不到XP共享的解决:

    不知道别人的是怎么解决. 反正我这么解决了. 我的win10笔记本,是使用windows帐户登陆的.可以同步很多东西. 同事的电脑是台式老古董XP. 扫描不到网上邻居,手动\\ip也访问不到. 最后安 ...

  10. 卷积与反卷积以及步长stride

    1. 卷积与反卷积 如上图演示了卷积核反卷积的过程,定义输入矩阵为 I(4×4),卷积核为 K(3×3),输出矩阵为 O(2×2): 卷积的过程为:Conv(I,W)=O 反卷积的过称为:Deconv ...