最长公共子序列问题描述


注意:最长公共子序列不一定是连续序列。
例如:"ASAFAGAHAJAK“与”AAAAAAA"的最长公共子序列为:AAAAAA

公共子序列的定义

证明最优子结构性质

分析其递归关系式

分别将第一个序列的元素个数设置为0到m,在每一个第一个序列的元素个数0到m的情况下,用内循环让第二个序列的元素从0到n遍历。

也就是说,先从0开始,求解很小的子问题,然后将这些子问题的解存储起来,当求解更大的问题时,会用到这些子问题的结果。这时,直接访问之前计算过的结果,避免了重复运算,这就是动态规划的巧妙之处,也正是需要证明其最优子结构性质的原因。

计算最优值

运行效果

c数组表示当前状态下,最长公共子序列的长度。
s数组表示当前状态下,最长公共子序列的长度是由哪种情况(1/2/3)计算出来的。

调试中的一个过程截取:

比如说,求解ABCDEFGHI和BDFI的最长公共子序列。

第一步(填0):
i=0,j=0,1,2,3,...时,因为X={},所以最长子序列都是0

第二步(填0):i=1,2,3,...,j=0时,因为Y={},所以最长子序列是0
(用这样的原理,把第一行和第一列都设置为0)

第三步(进入正常循环):
i=1,j=1时,也就是说当X的长度为1,Y的长度为1的条件下,X={A}Y={B},属于情况三(X Y的最后一个元素不相等)
此时,比较X={},Y={B}X={A},Y={}这两种情况下的公共子序列的值,将二者最大值(本例中为0)记录在数c数组中的c[i][j]位置。
同时,这种情况属于第三种,记为s[i][j]=3


根据第三步类推

某一个计算瞬间的详细分析如下

下图为调试过程中,截取的i=2,j=4时候的情况。当前被填写的数组元素:c[2][4]

此时,X={A,B},Y={B,D,F,I}
比较X与Y的最后一个元素,分别为B,I。发现其属于情况三(X Y的最后一个元素不相等)

于是,比较X去掉最后一个元素的最长公共子序列Y去掉最后一个元素的最长公共子序列,比较过程如下:
X去掉最后一个元素后,X={A},Y={B,D,F,I},查c数组得:其最长公共子序列为 c[i-1][j]=0
Y去掉最后一个元素后,X={A,B},Y={B,D,F},查c数组得:其最长公共子序列为 c[i][j-1]=1
比较结果为:取最大(后者)。 c[i][j] = c[i][j - 1] = 1,即另 c[2][4] = c[2][3] = 1

同时,因为是情况三,所以另 s[2][4] = 3

从下图可以看到,c[2][4] = 1已经被填入生效。刚才的分析与实际运行结果相匹配。

…其余中间过程省略

完整填写c数组和s数组之后,最终执行结果↓

补充:填表的顺序图示

输出:BDFI

输出的过程

输出序列字母的过程是一个递归的过程。

见下图,根据s数组判断下一个箭头的指向。可以把s数组的3种情况分别对应到三个指向的箭头,放在数组表格中。然后从右下角的元素开始,一步一步沿着箭头向前走。

或者单步跟踪一下代码比较容易理解。

详细输出过程图示:

代码

注意:需要在宏定义中手动输入序列X,Y的长度,在main函数中输入序列X,Y的具体序列

#include<iostream>
#include<cstring>
#define XLEN 12
#define YLEN 7
using namespace std;int c[XLEN + 1][YLEN + 1];//Xi Yj的最长公共子序列的长度 多出1行用来存放长度为0的情况
int s[XLEN + 1][YLEN + 1];//c[i][j]的值是由哪一个子问题的解得到的void lcsLength(string x, string y)
{for (int i = 0; i <= XLEN; i++) c[i][0] = 0;for (int i = 0; i <= YLEN; i++) c[0][i] = 0;for (int i = 1; i <= XLEN; i++)     //xi的长度{for (int j = 1; j <= YLEN; j++)  //yj的长度{if (x[i - 1] == y[j - 1]) //x y序列 最后一个元素相等{c[i][j] = c[i - 1][j - 1] + 1;s[i][j] = 1;}else                     //x y序列 最后一个元素不相等{if (c[i - 1][j] >= c[i][j - 1])   //x去掉现有序列最后一个元素更大{c[i][j] = c[i - 1][j];s[i][j] = 2;}else                         //y去掉现有序列最后一个元素更大{c[i][j] = c[i][j - 1];s[i][j] = 3;}}}}
}
void lcs(int i, int j, string x)
{if (i == 0 || j == 0)return;if (s[i][j] == 1) //x[i] == y[j]{lcs(i - 1, j - 1, x);cout << x[i - 1];}else if (s[i][j] == 2)//c[i - 1][j] >= c[i][j - 1]{lcs(i - 1, j, x);}else lcs(i, j - 1, x);//c[i - 1][j] < c[i][j - 1]
}int main()
{string x = "ASAFAGAHAJAK";string y = "ASAAAAA";lcsLength(x, y);lcs(XLEN, YLEN, x);cout << endl;system("pause");
}

【算法设计与分析】最长公共子序列问题 动态规划算法 超详细相关推荐

  1. 计算机算法设计与分析 最长递增子序列

    求一个字符串的最长递增子序列的长度.设计基于动态规划思想的算法. 如:dabdbf最长递增子序列就是abdf,长度为4 输入第一行一个整数0<n<20,表示有n个字符串要处理,随后的n行, ...

  2. 文本比较算法Ⅶ——线性空间求最长公共子序列的Nakatsu算法

    在参阅<A Longest Common Subsequence Algorithm Suitable for Similar Text Strings>(Narao Nakatsu,Ya ...

  3. 两个字符串的最长公共子序列长度_算法学习笔记(58): 最长公共子序列

    (为什么都更了这么多篇笔记了,这时候才讲这么基础的内容呢?因为我本来以为LCS这种简单的DP不用讲的,结果CF不久前考了LCS的变式,然后我发现由于自己对LCS一点都不熟,居然写不出来 ,于是决定还是 ...

  4. 用动态规划算法实现最长公共子序列问题的算法(java实现)

    用动态规划算法实现最长公共子序列问题的算法 public class longestCommonSubsequence {//构造追踪数组rec,记录子问题来源private static Strin ...

  5. 最长公共子序列问题——LCS算法

    最长公共子序列问题--LCS算法 问题描述: 给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的).比如两个串为:abcicba abdkscabab是两个串的子序列,abc也是,a ...

  6. 最长公共子序列算法 java,算法学习——java实现最长公共子序列,

    算法学习--java实现最长公共子序列学习--java实现最长公共子序列的算法, 实验目的: 输入两个同类型的序列,用动态规划的方法计算它们最长的公共子序列的长度和序列. (推荐教程: Java视频教 ...

  7. 国科大计算机算法设计与分析陈玉福,中科院陈玉福计算机算法设计与分析期末简答题答案.pdf...

    中科院陈玉福计算机算法设计与分析期末简答题答案 1. 贪心算法和动态规划算法有什么共同点和区别?它们都有那些优势和劣势? 共通点:动态规划和贪心算法都是一种递推算法 ,均有局部最优解来推导全局最优解 ...

  8. 【算法设计与分析】 单源最短路径(贪心算法) Dijkstra

    [算法设计与分析] 单源最短路径(贪心算法) Dijkstra [问题描述] Dijkstra算法解决的是带权重的有向图上单源最短路径问题.所有边的权重都为非负值.设置顶点集合S并不断地作贪心选择来扩 ...

  9. 国科大计算机算法设计与分析陈玉福,中科院陈玉福计算机算法设计与分析期末简答题答案...

    中科院陈玉福计算机算法设计与分析期末简答题答案 1. 贪心算法和动态规划算法有什么共同点和区别?它们都有那些优势和劣势? 共通点:动态规划和贪心算法都是一种递推算法 ,均有局部最优解来推导全局最优解 ...

最新文章

  1. iOS端Socket(二)ProtocolBuffer使用
  2. 一封建议信,不知道这样写可以吗?
  3. react生命周期-新增与替换
  4. 检测生成.xml文件的效果:以人脸xml为例
  5. 图像检索:基于形状特征的算法
  6. DevExpress的更新
  7. js对象、构造函数、命名空间、方法、属性
  8. 建立ARM交叉编译环境 (arm-none-linux-gnueabi-gcc with EABI)
  9. 正则表达式||grep的使用
  10. 上传文件显示进度条_文件上传带进度条进阶-断点续传
  11. android media apex_APEX英雄主播即将登陆时代广场?人气十强介绍!
  12. python怎样把if语句写成一行_python:将一个简单的if-then-else语句放在一行上
  13. 谷歌语音识别_谷歌 语音识别 语种 - 云+社区 - 腾讯云
  14. 基于pycrfsuite和sklearn_crfsuite的命名实体识别NER实战【以CoNLL2002数据集为基准】
  15. sqlite数据库下载安装和初步操作和所遇到的问题
  16. 清理计算机磁盘碎片,如何清理磁盘碎片
  17. Python暴力破解教程: Zip加密文件, pdf加密书籍在线爆破!
  18. Spring OAuth2 授权服务器配置详解
  19. python跳到微软商城解决 cocos 所有指令没有反应解决方法
  20. 推荐使用:易企在线客服升级版

热门文章

  1. Docker教程-文件传输
  2. 关于landau函数
  3. POJ2528 线段树+离散化+hash(成段更新)
  4. 8.元组tup.rs
  5. 高可用系统设计 | 分布式限流策略:计数器算法、漏桶算法、令牌桶算法
  6. 可接受任意数量参数的函数
  7. JS组件系列——表格组件神器:bootstrap table
  8. 深入理解Netty高性能网络框架
  9. 音视频技术开发周刊 | 193
  10. LiveVideoStack主编观察03 /大会见闻思考