最长公共子序列与最长公共子串--动态规划
来源:互联网 发布:淘宝智能版首页尺寸 编辑:程序博客网 时间:2024/06/09 18:37
最长公共子串(Longest Common Substirng)和最长公共子序列(Longest Common Subsequence,LCS)的区别为:子串是串的一个连续的部分,子序列则是从不改变序列的顺序,而从序列中去掉任意的元素而获得新的序列;也就是说,子串中字符的位置必须是连续的,子序列则可以不必连续。
最长公共子序列
问题:对于母串X=<x1,x2,⋯,xm>
,Y=<y1,y2,⋯,yn>
,求LCS与最长公共子串。
动态规划解决:
假设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)的核心思想了。
用二维数组c[i][j]
记录串x1x2⋯xi
与y1y2⋯yj
的LCS长度,则可得到状态转移方程:
代码实现:
#include<iostream>#include<string.h>#include<algorithm>#define MAX 1005using namespace std;int temp[MAX][MAX];int LCS(string &s1,string &s2){ memset(temp,0,MAX*sizeof(int)); int len1 = s1.length(); int len2 = s2.length(); for(int i = 0; i < len1; i++){ for(int j = 0; j < len2; j++){ if(s1[i] == s2[j]){ temp[i+1][j+1] = temp[i][j]+1;//从下标(1,1)开始存储 }else{ temp[i+1][j+1] = max(temp[i+1][j],temp[i][j+1]); } } } return temp[len1][len2]; }
代码解释:
其实就是一个填充二维数组记录状态的过程。
假设s1='blog'
,s2='long'
则记录状态的二维数组temp为:
解释下temp:纵向为s1字符串的下标,横向为s2字符串的下标
第三行:用s1(‘blog’)的b
去匹配逐一匹配s2(‘long’),因为s2没有b
,所以记录下的公共子序列都为0.
第四行:用s1(‘blog’)的l
去匹配逐一匹配s2(‘long’),第一个匹配到了l,所以可以确定目前的最长公共子序列长度为1,然后接着匹配,o,n,g
都与l
不匹配,所以就从上方(temp[i][j+1])和左侧(temp[i+1][j])选取最大者。(原因:上方表示b
匹配到的最长公共子序列,左侧表示bl
目前匹配到的最长公共子序列)
剩下的原理都相同。
最长公共子串
考虑到子串的连续性,将二维数组c[i,j]c[i,j]用来记录具有这样特点的子串——结尾为母串x1x2⋯xi
与y1y2⋯yj
的结尾——的长度。
状态方程为:(子串只需在意之前的序列长度就行了)
代码:
#include<iostream>#include<string.h>#include<algorithm>#define MAX 1005using namespace std;int temp[MAX][MAX];int result = 0;;int LCS(string &s1,string &s2){ memset(temp,0,MAX*sizeof(int)); int len1 = s1.length(); int len2 = s2.length(); for(int i = 0; i < len1; i++){ for(int j = 0; j < len2; j++){ if(s1[i] == s2[j]){ temp[i+1][j+1] = temp[i][j]+1; result = max(temp[i+1][j+1],result);//记录下最大值 }else{ temp[i+1][j+1] = 0; } } } return result; }
- 最长公共子序列&&最长公共子串---[动态规划]
- 动态规划-最长公共子序列、最长公共子串
- 动态规划--最长公共子序列和公共子串
- 【动态规划】最长公共子序列与最长公共子串
- 【动态规划】最长公共子序列与最长公共子串
- 【动态规划】最长公共子序列与最长公共子串
- 动态规划:最长公共子序列与最长公共子串
- 最长公共子序列与最长公共子串--动态规划
- 动态规划 最长公共子序列LCS、最长公共连续子串、最长重复子串
- 动态规划之最长递增子序列 最长不重复子串 最长公共子序列
- 动态规划之最长递增子序列 最长不重复子串 最长公共子序列
- 动态规划之最长公共子序列
- 动态规划 ------- 最长公共子序列
- 动态规划实现最长公共子序列
- 【动态规划】最长公共子序列LCS
- 动态规划--最长公共子序列
- 动态规划:最长公共子序列
- 动态规划解决最长公共子序列
- MongoDB 聚合管道(Aggregation Pipeline)
- 高效实用Android Studio (一)
- 【剑指offer】面试题16:数值的整数次方
- [bzoj4196][树链剖分][Noi2015]软件包管理器
- 拓扑排序(C语言 邻接矩阵存储)
- 最长公共子序列与最长公共子串--动态规划
- 复习到了快排,简单练一下笔
- numpy中的tile函数
- Java数组,构造方法,this关键字例题全解--经典问题
- Java案例使用for循环+switch case+if else的猜拳小游戏
- J2EE进阶之servlet 九
- 7.18
- win10 uwp 使用 Geometry resources 在 xaml
- k近邻算法简介及源代码(含图象打印)