实验3、最长公共子序列

问题描述与实验目的:

序列Z=<B,C,D,B>是序列X=<A,B,C,B,D,A,B>的子序列,相应的递增下标序列为<2,3,5,7>。

一般地,给定一个序列X=<x1,x2,…,xm>,则另一个序列Z=<z1,z2,…,zk是X的子序列,是指存在一个严格递增的下标序列〈i1,i2,…,ik〉使得对于所有j=1,2,…,k使Z中第j个元素zj与X中第ij个元素相同。

给定2个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。

你的任务是:给定2个序列X、Y,求X和Y的最长公共子序列Z。

输入

输入文件中的第1行是一个正整数T,(0<T<=10),表示有T组测试数据。接下来是每组测试数据的描述,每组测试数据有3行。

测试数据的第1行有2个正整数m、n,中间用一个空格隔开,(0<m,n<50);第2、3行是长度分别为m、n的2个序列X和Y,每个序列的元素间用一个空格隔开。序列中每个元素由字母、数字等构成。

输入直到文件结束。

输出

对输入中的每组测试数据,输出2行。先在一行上输出“Case #”,其中“#”是测试数据的组号(从1开始),再在第2行上输出这2个序列X、Y的最长公共子序列Z的长度及子序列Z(至少一个)。

实验结果:

输入样例

2

7 6

A B C B D A B

B D C A B A

8 9

b a a b a b a b

a b a b b a b b a

输出

Case 1

4 LCS(X,Y):B C B A

Case 2

6 LCS(X,Y):a b a b a b

实验报告要求:

1.先分析要点、写出动态方程

2.提供能正确运行的程序,有注释。要有一般性,即可同时处理若干组数据,每组3行。如有潜能,写程序找出所有的最长公共子序列。

3.设计、调试中的问题及实验体会。

要求:个人可根据自己情况进行选择,验收时根据完成情况评分

  1. 第一层次 铜牌要求(基本要求),能输出最长公共子序列的长度(通过在线判题系统);
  2. 第二层次 银牌要求,在输出最长公共子序列的长度的基础上,再输出表格c表和b表,并输出一条最长公共子序列;
  3. 第三层次 金牌要求,在铜牌要求的基础上,输出全部的最长公共子序列。

解答:

1. 分析

最长公共子序列具有最优子结构性质:

X=x1,x2,  ……  xm  和 Y=y1,y2,  ……  yn    的最长公共子序列为

Z=z1,z2,  ……  zk  , 则

  1. xm=yn  ,则zk=xm=yn ,且Zk-1 是 Xm-1 和 Yn-1的最长公共子序列。
  2. xmyn  ,则zk≠xm ,则Zk-1 是 Xm-1 和 Yn的最长公共子序列。
  3. xmyn  ,则zk≠yn ,则Zk-1 是 Xm 和 Yn-1的最长公共子序列。

2. 动态规划方程:

用c[i][j]记录序列X和Y的最长公共子序列长度。

当i=0或j=0时,c[i][j]=0;

递归关系如下:

  1. 代码解析:

本代码实现了金牌算法:所有最长公共子序列的输出,并进行了去重复操作。

关键代码如下:

  1. //1. 求最长公共子序列长度代码:
    void LCSLength(int m, int n, char* x, char* y, int** c, int** b)
    {int i, j;for (i = 1; i <= m; i++){c[i][0] = 0;}for (j = 1; j <= n; j++){c[0][j] = 0;}for (i = 1; i <= m; i++)for (j = 1; j <= n; j++){if (x[i] == y[j]) {c[i][j] = c[i - 1][j - 1] + 1;b[i][j] = 1;}else if (c[i - 1][j] > c[i][j - 1]){c[i][j] = c[i - 1][j];b[i][j] = 2;}else if (c[i - 1][j] < c[i][j - 1]){c[i][j] = c[i][j - 1];b[i][j] = 3;}else{c[i][j] = c[i - 1][j];b[i][j] = 4;}}
    }
    //2. 构造输出
    void LCS(int i, int j, char* x, int** b, vector<string>& out,int &flag,int &index)
    {if (i == 0 || j == 0){out[index] += "\n";return;}if (b[i][j] == 1){LCS(i - 1, j - 1, x, b, out,flag,index);out[index] += x[i];out[index] += " ";}else if (b[i][j] == 2)LCS(i - 1, j, x, b, out,flag,index);else if (b[i][j] == 3)LCS(i, j - 1, x, b, out,flag,index);else{LCS(i - 1, j, x, b, out,flag,index);b[i][j] = 3;flag++;}
    }

3. 程序调试及实验截图:​

所有最长公共子序列,输出结果如下,源代码随附录附上:

​​​

4. 体会:

  1. 本题如登山一样,不同要求有不同难度,例如在实现输出最长公共子序列长度,只需要一个小时即可,而实现输出一个最长公共子序列,则耗费了3小时,最后将所有最长公共子序列一个不少,一个不重复的输出,则耗费了近6个消失。
  2. 这类递归算法,弄清整个过程是解题的关键,哪个变量会产生不同的答案,采用什么样 的解决方法,在实现本题过程中,我都有相应的学习和体会。

5.  源代码及注释:

#include<iostream>
#include<string>
#include<vector>
using namespace std;void LCSLength(int m, int n, char* x, char* y, int** c, int** b)
{int i, j;for (i = 1; i <= m; i++){c[i][0] = 0;}for (j = 1; j <= n; j++){c[0][j] = 0;}for (i = 1; i <= m; i++)for (j = 1; j <= n; j++){if (x[i] == y[j]) {c[i][j] = c[i - 1][j - 1] + 1;b[i][j] = 1;}else if (c[i - 1][j] > c[i][j - 1]){c[i][j] = c[i - 1][j];b[i][j] = 2;}else if (c[i - 1][j] < c[i][j - 1]){c[i][j] = c[i][j - 1];b[i][j] = 3;}else{c[i][j] = c[i - 1][j];b[i][j] = 4;}}
}void LCS(int i, int j, char* x, int** b, vector<string>& out,int &flag,int &index)
{if (i == 0 || j == 0){out[index] += "\n";return;}if (b[i][j] == 1){LCS(i - 1, j - 1, x, b, out,flag,index);out[index] += x[i];out[index] += " ";}else if (b[i][j] == 2)LCS(i - 1, j, x, b, out,flag,index);else if (b[i][j] == 3)LCS(i, j - 1, x, b, out,flag,index);else{LCS(i - 1, j, x, b, out,flag,index);b[i][j] = 3;flag++;}
}int flag_out = 0;  //总输出变量int main() {int num=0;//确定输入几组数据int m, n,flag=0;               //flag是b=4时候,返回的标记cin >> num;vector<string> out(40);for (int i = 0; i < num; i++)       //输入数据,同时处理{out[flag_out] += "\nCase " + to_string(i+1)+"\n";cin >> m >> n;char* x = new char[m + 1];char* y = new char[n + 1];int** c = new int* [m + 1];int** b = new int* [m + 1];for (int j = 0; j <= m; j++){c[j] = new int[n + 1];b[j] = new int[n + 1];}for (int j = 1; j <= m; j++)cin >> x[j];    //Y数组for (int j = 1; j <= n; j++)cin >> y[j];      //Y数组//从x开始先删去元素LCSLength(m, n, x, y, c, b);out[flag_out] += to_string(c[m][n]) + " LCS(X,Y):";flag_out++;for(int i=0;i<=flag;i++,flag_out++)LCS(m, n, x, b, out, flag,flag_out);//从y开始先删去元素LCSLength(m, n, y, x, c, b);for (int i = 0; i <= flag; i++, flag_out++){LCS(m, n, y, b, out, flag, flag_out);}}for (int i = 0; i < out.size(); i++)for(int j=i+1;j< out.size();j++)if (out[i] == out[j]){out.erase(out.begin() + j);j--;}for (int i = 0; i < out.size(); i++)cout << out[i];return 0;
}

实验三、最长公共子序列(输出所有最长公共子序列)相关推荐

  1. 算法:最长公共子序列(输出所有最长公共子序列)

    问题描述:给定两个序列,例如 X = "ABCBDAB".Y = "BDCABA",求它们的最长公共子序列的长度. 下面是求解时的动态规划表,可以看出 X 和 ...

  2. 数组字符串那些经典算法:最大子序列和,最长递增子序列,最长公共子串,最长公共子序列,字符串编辑距离,最长不重复子串,最长回文子串 (转)...

    作者:寒小阳 时间:2013年9月. 出处:http://blog.csdn.net/han_xiaoyang/article/details/11969497. 声明:版权所有,转载请注明出处,谢谢 ...

  3. 【恋上数据结构】动态规划(找零钱、最大连续子序列和、最长上升子序列、最长公共子序列、最长公共子串、0-1背包)

    动态规划(Dynamic Programming) 练习1:找零钱 找零钱 - 暴力递归 找零钱 - 记忆化搜索 找零钱 - 递推 思考题:输出找零钱的具体方案(具体是用了哪些面值的硬币) 找零钱 - ...

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

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

  5. 用dsp的c54x汇编语言编写4位数的按位输出和计算,DSP实验三实验四(精).doc

    DSP实验三实验四(精).doc 实验三.文件和Gel文件的编写 一.实验目的 1. 掌握Gel文件的编写, 2. 熟悉Code Composer Studio的使用 二.实验设备 1. 集成开发环境 ...

  6. 求三个长方柱的体积,数据成员包括length(长)、width(高)。要求用成员函数实现以下功能: (1)用键盘分别输入三个长方柱的长宽高; (2)计算长方柱的体积;(3)输出3个长方柱的体积。

    项目要求: 需要求三个长方柱的体积,请编写一个基于对象的程序,数据成员包括length(长).width(高).要求用成员函数实现以下功能: (1)用键盘分别输入三个长方柱的长宽高: (2)计算长方柱 ...

  7. PTA | 实验三 输出前 n 个Fibonacci数

    本题要求编写程序,输出菲波那契(Fibonacci)数列的前N项,每行输出5个,题目保证输出结果在长整型范围内.Fibonacci数列就是满足任一项数字是前两项的和(最开始两项均定义为1)的数列,例如 ...

  8. 用计算机计算线性卷积的基本规则,实验三_线性卷积与圆周卷积的计算.doc

    实验三_线性卷积与圆周卷积的计算 电信类课程试验报告 学 院:基础信息工程系 别:电子信息工程课程名称:数字信号处理姓 名:学 号:日 期:实验三实验名称:线性卷积与圆周卷积的计算一.实验目的 (1) ...

  9. 实验三 面向对象(二)

    实验三 面向对象(二) <center> <strong>姓名:</strong> <u>XXX</u>    <strong> ...

最新文章

  1. Linux 段错误详解
  2. 性能不同的服务器可以组成云,多个服务器组成云
  3. 10G_Ethernet_04 10G Ethernet Subsystem IP 的快速验证(万兆以太网IP的快速验证)
  4. linux按键检测结束,关于Linux下按键的检测
  5. 微软Silverlight 5开发书籍汇总
  6. Windows下openssl的下载安装和使用
  7. 配置和使用APM功能和调用链分析功能
  8. 一些常用的WebServices
  9. AI加持,计算机要拥有嗅觉了;GPU终于可用于Google Compute Engine | AI开发者头条
  10. 斐讯k1潘多拉专版固件_斐讯路由器刷潘多拉固件+宽带并发多拨号视频教程+工具下载(K1K2)...
  11. CCNA中文版完整教程
  12. 16、单片机串口原理与应用
  13. qcap 教程_高通平台抓取ramdump及使用qcap解析,ramdumpqcap
  14. MATLAB-SIMULINK-二极管搭建整流电路(1)
  15. url 与 domain
  16. 两年数据对比柱形图_同期数据对比,你会做这样特殊的柱形图吗?趋势、差异值一目了然...
  17. Java串口通信读写串口导致程序崩溃问题
  18. 微信小程序web-view与H5 通信方式探索
  19. YY内置灯笼号挂号工具
  20. java容器系列一(java容器Collection概述)

热门文章

  1. Flink系列之:Java代码实现深入浅出的理解Flink算子的使用方法
  2. 衣物洗涤领域,RFID技术前景广阔
  3. java中set的遍历_java中遍历set集合,java中set怎么遍历?
  4. linux与windows市场占有率,Windows 10 Mobile市场份额已达14%
  5. i5 1240p和酷睿i7 1195g7 选哪个好?区别对比评测
  6. PS基础-通道、蒙版
  7. pip使用阿里云源进行加速
  8. rcnn 回归_目标检测-从RCNN到Mask RCNN两步检测算法总结-火龙果软件
  9. ES5-数组API:arr.indexOf、arr.every(条件)、arr.some(条件)、arr.forEach()遍历、arr.map()、filter过滤、reduce汇总
  10. API(Application Programming Interface)