最长公共子序列与最长公共字串 (dp)转载http://blog.csdn.net/u012102306/article/details/53184446
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的更多相关文章
- [Python]最长公共子序列 VS 最长公共子串[动态规划]
前言 由于原微软开源的基于古老的perl语言的Rouge依赖环境实在难以搭建,遂跟着Rouge论文的描述自行实现. Rouge存在N.L.S.W.SU等几大子评估指标.在复现Rouge-L的函数时,便 ...
- hdu 1950 最长上升子序列(lis) nlogn算法【dp】
这个博客说的已经很好了.http://blog.csdn.net/shuangde800/article/details/7474903 简单记录一下自己学的: 问题就是求一个数列最长上升子序列的长度 ...
- [Data Structure] LCSs——最长公共子序列和最长公共子串
1. 什么是 LCSs? 什么是 LCSs? 好多博友看到这几个字母可能比较困惑,因为这是我自己对两个常见问题的统称,它们分别为最长公共子序列问题(Longest-Common-Subsequence ...
- 动态规划 最长公共子序列 LCS,最长单独递增子序列,最长公共子串
LCS:给出两个序列S1和S2,求出的这两个序列的最大公共部分S3就是就是S1和S2的最长公共子序列了.公共部分 必须是以相同的顺序出现,但是不必要是连续的. 选出最长公共子序列.对于长度为n的序列, ...
- 【ZH奶酪】如何用Python计算最长公共子序列和最长公共子串
1. 什么是最长公共子序列?什么是最长公共子串? 1.1. 最长公共子序列(Longest-Common-Subsequences,LCS) 最长公共子序列(Longest-Common-Subseq ...
- 用Python计算最长公共子序列和最长公共子串
如何用Python计算最长公共子序列和最长公共子串 1. 什么是最长公共子序列?什么是最长公共子串? 1.1. 最长公共子序列(Longest-Common-Subsequences,LCS) 最长公 ...
- 动态规划1——最长递增子序列、最长公共子序列、最长公共子串(python实现)
目录 1. 最长递增序列 2. 最长公共子序列 3. 最长公共子串 1. 最长递增序列 给定一个序列,找出其中最长的,严格递增的子序列的长度(不要求连续). 解法一:动态规划 通过一个辅助数组记录每一 ...
- O(n log n)求最长上升子序列与最长不下降子序列
考虑dp(i)表示新上升子序列第i位数值的最小值.由于dp数组是单调的,所以对于每一个数,我们可以二分出它在dp数组中的位置,然后更新就可以了,最终的答案就是dp数组中第一个出现正无穷的位置. 代码非 ...
- 最长公共子序列PK最长公共子串
1.先科普下最长公共子序列 & 最长公共子串的区别: 找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的.而最长公共子序列则并不要求连续. (1)递归方法求最长公共子序列的长度 1) ...
随机推荐
- java反序列化漏洞原理研习
零.Java反序列化漏洞 java的安全问题首屈一指的就是反序列化漏洞,可以执行命令啊,甚至直接getshell,所以趁着这个假期好好研究一下java的反序列化漏洞.另外呢,组里多位大佬对反序列化漏洞 ...
- Spring Cloud之路:(七)SpringBoot+Shiro实现登录认证和权限管理
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/sage_wang/article/details/79592269一.Shiro介绍1.Shiro是 ...
- Weka中数据挖掘与机器学习系列之数据格式ARFF和CSV文件格式之间的转换(五)
不多说,直接上干货! Weka介绍: Weka是一个用Java编写的数据挖掘工具,能够运行在各种平台上.它不仅提供了可以直接用于数据挖掘的软件,还提供了src代码,使用者可以修改源代码,进行二次开发. ...
- centos6.5+python2.7+flask+apache+mod-wsgi部署
flask部署,使用的是centos6.5,python2.7,版本很重要.基本步骤如下: 一.创建虚拟环境,创建目录把项目拷进去 二.安装mod-wsgi和apache easy_install m ...
- 关于iOS设备的那些事
首先推荐一个在用的库XYQuick 地址:https://github.com/uxyheaven/XYQuick idfa: 获取方式 [ASIdentifierManager sharedMana ...
- (Java学习笔记) Java Networking (Java 网络)
Java Networking (Java 网络) 1. 网络通信协议 Network Communication Protocols Network Protocol is a set of rul ...
- 3.6 C++继承机制下的构造函数
参考:http://www.weixueyuan.net/view/6363.html 总结: 在codingbook类中新增了一个language成员变量,为此必须重新设计新的构造函数.在本例中bo ...
- Oracle中把一张表查询结果插入到另一张表中
1. 新增一个表,通过另一个表的结构和数据 create table XTHAME.tab1 as select * from DSKNOW.COMBDVERSION 2. 如果表存在: inse ...
- C#正则表达式类Match和Group类的理解
正则表达式可以看做一种有特定功能的小型编程语言,在一段文本中定位子字符串.利用正则表达式可以快速地分析大量的文本以找到特定的字符模式:提取.编辑.替换或删除文本子字符串:或将提取的字符串添加到集合.正 ...
- <顺序访问><随机访问><HDFS>
Overview 如果你了解过HDFS,至少看过这句话吧: HDFS is a filesystem designed for storing very large files with stream ...