问题描述: 这个问题其实很容易理解。就是给你两个序列X={x1,x2,x3......xm} Y={y1,y2,y3......ym},要求找出X和Y的一个最长的公共子序列。

例:Xi={A, B, C, B, D, A}    Yj={B, C, A, B, A}  求得 Z={B, C, B, A}

问题详解: 那么问题来了,我们如何去求解出最终的过程呢?既然是复习周,那我就开门见山,直接用DP算法去解决这个问题。

分析:该问题具有最优子结构的性质。

这里我们使用上面的那个例子:我们此时倒着进行分析

①当我们知道了最长公共子序列为Z={B,C,B,A}的时候,我们知道当取Xi序列的最后一个值x6=A与Yi序列的最后一个值Y5=A,此时X6=Y5,则z4=X6=Y5,就得出来的 Z1~Z3 为 X1~X5 与 Y1~Y4 的最长公共子序列。

②再往前走,X5=D而Y4=B我们知道  x5!=Y4  所以Z1~Z3是  X1~X5 与 Y1~Y3的子序列 或者是 X1~X4 与 Y1~Y4的子序列(这里这个例子是——Z{B,C,B}是A{A,B,C,B}与B{B,C,A,B}的公共子序列)

也许文字不太好理解,但是我们由此可以归纳出一个递推公式:

而C[i][j]中存的是序列X1~Xi与序列Y1~Yj的最长公共子序列长度。

下面我们来看具体的寻找方法——>

  这里我们放一道例题:

给定两个序列为X=<A, B, C, B, D, A, B>和 Y=<B, D, C, A, B, A>,求最长公共子序列?

这个时候我们需要递归来填写出数组中的数字。

①我们来画出这个二维数组。

②因为0行0列并没有实际的意义,所以我们填上0。

③之后,我们开始递归写表。此时我们要知道,行数1~7代表X的各个数字,而列为Y的数字。当i=1是代表我拿出来X数列中的A,j=1代表我拿出来Y数列中的B。然后比较发现A!=B  所以我们判断max(C[0][1],C[1][0])--其实我们写算法的时候都默认从上面继承下来。发现都是0,所以C[1][1]=0。

④同样的情况一直到C[1][4]这个地方,此时我们发现X1=A,Y4=A。X1=Y4。所以我们调用C[i][j]=C[i-1][j-1]函数,从左上角继承下来。C[1][4]=C[0][3]=0+1=1。

。。。。。最后填写完成后为:

(其实算法思想很简单,就是当前两个数相同就左上角的值+1,不相同就比较左边和上面,找大的写上去)

此时我们就要进入下一步,就是根据这个表去找到最长公共子序列。

而在上面的每一步填写表格的时候,我们需要加上一步——就是记录我当前的这个格子的值是从什么位置继承来的。(创建一个新的二维数组)  这里我们规定:

①当C[i][j]是从左上角+1得来的,我们在b[i][j]处填上1。

②当C[i][j]是从左侧继承来的,b[i][j]=3。

③当C[i][j]从上面继承来的,b[i][j]=2。

我们这里得到b[i][j]

之后我们从最右下角的位置开始,根据b中的表格得到:

这个时候我们取箭头的末端所在行——第2、3、4、6行,对应X序列中的B,C,B,A。由此得到Z序列。

算法代码:

  因为这道题目要考上机题,所以我在这里把代码思想也放到这里,不过代码很简单这里就不详细叙述了

#include<iostream>
#include<string.h>
using namespace std;
int C[][];
int bb[][];
char A[];
int LCS(char a[],char b[],int a_len,int b_len){
for(int i =;i<;i++){
C[][i]=;
C[i][]=;
}
for(int h=;h<=a_len;h++){
for(int hh=;hh<=b_len;hh++){
if(a[h-]==b[hh-]) {
C[h][hh]=C[h-][hh-]+;
bb[h][hh]=;
}
else{
if(C[h-][hh]>=C[h][hh-]) {
C[h][hh]=C[h-][hh];
bb[h][hh]=; }
if(C[h-][hh]<C[h][hh-]){
C[h][hh]=C[h][hh-];
bb[h][hh]=;
}
}
}
}
}
int LCScout(int a,int b){
if(a==||b==) return ;
else{
if(bb[a][b]==) {
LCScout(a-,b-);
cout<<A[a-];
}
if(bb[a][b]==){
LCScout(a-,b);
}
if(bb[a][b]==){
LCScout(a,b-);
}
}
}
int main(){ char B[];
cin>>A;
cin>>B;
int A_len = strlen(A);
int B_len = strlen(B);
LCS(A,B,A_len,B_len);
LCScout(A_len,B_len); }

上面的代码是我自己写着玩的一些寻找最长公共序列的方法,下面我在放上计蒜课上的——《最长共公子串》

#include<iostream>
#include<string.h>
using namespace std;
int lcs[][];
int b[][]; int LCS(char A[],char B[],int a_len,int b_len){
int max=;
for(int i=;i<=;i++){
lcs[][i]=;
lcs[i][]=;
}
for(int i=;i<=a_len;i++){
for(int h=;h<=b_len;h++){
if(A[i-]==B[h-]) {
lcs[i][h]=lcs[i-][h-]+;
if(lcs[i][h]>max) max=lcs[i][h];
b[i][h]=;
}
else{
if(lcs[i-][h]>=lcs[i][h-]){
lcs[i][h]=lcs[i-][h];
b[i][h]=;
}
else{
lcs[i][h]=lcs[i][h-];
b[i][h]=;
}
}
}
}
return max;
}
int main(){
char A[];
char B[];
cin>>A;
cin>>B;
int A_len = strlen(A);
int B_len = strlen(B); cout<<LCS(A,B,A_len,B_len);
}

是不是很基础~相信大家算法考试应该问题不大~加油加油!

——————————————————————————————————————Made By Pinging

算法复习周------“动态规划之‘最长公共子序列’”&&《计蒜课》---最长公共子串题解的更多相关文章

  1. Luogu 3402 最长公共子序列(二分,最长递增子序列)

    Luogu 3402 最长公共子序列(二分,最长递增子序列) Description 经过长时间的摸索和练习,DJL终于学会了怎么求LCS.Johann感觉DJL孺子可教,就给他布置了一个课后作业: ...

  2. codevs 1862 最长公共子序列(求最长公共子序列长度并统计最长公共子序列的个数)

    题目描述 Description 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y ...

  3. 动态规划经典——最长公共子序列问题 (LCS)和最长公共子串问题

    一.最长公共子序列问题(LCS问题) 给定两个字符串A和B,长度分别为m和n,要求找出它们最长的公共子序列,并返回其长度.例如: A = "HelloWorld"    B = & ...

  4. 最长递增子序列(lis)最长公共子序列(lcs) 最长公共上升子序列(lics)

    lis: 复杂度nlgn #include<iostream> #include<cstdio> using namespace std; ],lis[],res=; int ...

  5. 最长公共子序列(LCS)最长递增子序列(LIS)

    #include<cstring>#include<iostream>#include<stack>#include <algorithm>using ...

  6. 动态规划---等和的分隔子集(计蒜课)、从一个小白的角度剖析DP问题

    自己还是太菜了,算法还是很难...这么简单的题目竟然花费了我很多时间...在这里我用一个小白的角度剖析一下这道题目. 晓萌希望将1到N的连续整数组成的集合划分成两个子集合,且保证每个集合的数字和是相等 ...

  7. 算法练习——最长公共子序列的问题(LCS)

    问题描述: 对于两个序列X和Y的公共子序列中,长度最长的那个,定义为X和Y的最长公共子序列.X  Y   各自字符串有顺序,但是不一定需要相邻. 最长公共子串(Longest Common Subst ...

  8. 【51NOD】1006 最长公共子序列Lcs(动态规划)

    给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为:   abcicba abdkscab   ab是两个串的子序列,abc也是,abca也是,其中abca是这两个 ...

  9. 【ACM】最长公共子序列 - 动态规划

    最长公共子序列 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 咱们就不拐弯抹角了,如题,需要你做的就是写一个程序,得出最长公共子序列.tip:最长公共子序列也称作最 ...

随机推荐

  1. RabbitMQ最佳实践

    在使用消息机制时,我们通常需要考虑以下几个问题: 消息不能丢失 保证消息一定能投递到目的地 保证业务处理和消息发送/消费的一致性 本文以RabbitMQ为例,讨论如何解决以上问题. 消息持久化 如果希 ...

  2. ARM PPC 交叉编译环境搭建

    ARM: 1,下载cross-3.4.1.tar.bz2 2,在/usr/local目录下建立arm目录 3,将cross-3.4.1.tar.bz2拷贝到arm目录下 4,tar jxvf cros ...

  3. canvas仿芝麻信用分仪表盘

    这是一个仿支付宝芝麻信用分的一个canvas,其实就是一个动画仪表盘. 首先, 上原图: 这个是在下支付宝上的截图,分低各位见笑了.然后看下我用canvas实现的效果图: <canvas id= ...

  4. sqlite中常见的问题总结

    一.sqlite中不能使用日期进行相减,执行结果无效 例如:SELECT count(*) as cnt FROM DayBanalces WHERE (date(ofDay)- date('2013 ...

  5. jquery显示和隐藏元素

    1.$('#id').show()/$('#id').hide()/$('#id').toggle() 2.$('#id').css('display','none')/$('#id').css('d ...

  6. Win8系统如何关闭用户账户控制UAC

    按WIN+S,屏幕右侧出现搜索框,在搜索框中输入UAC,然后单击"更改用户账户控制设置"   然后把弹出的窗口改成"从不通知"就可以了  

  7. Android调试工具_ Stetho

    Stetho是Facebook开源的一个Android平台调试工具. Stetho能实如今不root手机的情况下,通过Chrome查看App的布局,Sqlite,SharedPreference.Ne ...

  8. 各种“GND”

    资料来自网上,把个人觉得靠谱的摘取下来 1.地分类: a)直流地:直流电路“地”,零电位参考点: b)交流地:交流电的零线.要与地线区别开,不过,有时候拉电入户之前会把地线和零线接在一起: c)功率地 ...

  9. 4 Ionic导航和核心组件--旅游应用

    简介:在本节课中,我们将会通过一个虚构的旅游景点来构建一款功能完善的应用.本应用的核心特性是管理用户的应用内导航.本节课的主要目的,是展现构建一个完整的应用的过程. 无论是什么移动应用,最重要的功能之 ...

  10. 嵌入式开发之davinci--- 8148/8168/8127 中的添加算饭scd 场景检测 文档简介

    Osd Scd (1)     Introduction over view a)         scene change detection block diagram a)         gr ...