动态规划简述

使用最优子结构特性,动态规划算法采用自底向上的方式计算,在求解的过程中保存已经计算好的子问题的最优解,当子问题的最优解被重复使用时,无需再次计算直接从保存的空间中调用。

举个例子: 斐波那契数列

后一项等于前两项累加之和,如果采用递归则一直要从n递归到0。

如果采用动态规划则计算前两项保存到数组之中,后面每一项都直接调用前两项之和累加并保存到数组之中供后面的元素调用,便不用占用计算时间。

最长公共子序列问题描述

 

 下图给出了最优解的递推关系

利用递推关系来生成最大子序列矩阵,再生成最大子序列矩阵的同时,生成一个回溯矩阵,用来回溯最大公共子序列都有哪些。

具体的算法思想

需要定义一下矩阵

int c[8][8]; //c计算并存储最大子序列
int s[8][8];    //s为回溯寻找子序列元素 1左上找并且为子序列元素 2上回溯 3左回溯

c[][]矩阵的生成

c[7][7]存储最大子序列个数,s存储回溯矩阵。

输入的公共序列为X:0abcbdab Y:0bdcaba

根据递推关系式,c矩阵第0行第0列都初始化为0;

当X第i个元素与Y的第j个元素相等时,c[i][j] = c[i-1][j-1] +1 也就是左上角的元素+1;

当X第i个元素与Y的第j个元素不相等时,这时我们要判断是上面的元素比左边的元素大,还是左边的元素比上面的元素大。

当c左边的元素大于等于上面的元素时,c[i][j] = c[i - 1][j],也就是等于左边的元素;

当c左边的元素小于上面的元素时,c[i][j] = c[i][j - 1];,也就是等于上面的元素;

这样计算完成的矩阵c的最后一个元素也就是最大公共子序列的个数。

s[][]矩阵的生成

s矩阵生成也分为三种情况,分别对应上面的递推关系的三种情况

1. 当X第i个元素与Y的第j个元素相等时,将s[i][j] = 1

2. 当c左边的元素大于等于上面的元素时,将s[i][j] = 2

3. 当c左边的元素小于上面的元素时,将s[i][j] = 3;

代码实现

这里我将生成c与s的代码直接放入主函数之中了,文章结尾给出全部代码

根据上面c[i][j]的递推关系,可以计算出矩阵c[][],在这里我们要注意,计算矩阵c之前需要初始化第0列和第0行,为了防止越界,实际上输入两个子序列时要在子序列之前加上‘0’,然后从子序列第1个元素开始判断。我们判断公共子序列也是从第一行开始判断防止上来c[i][j]出现递推关系中的第二种或者第三种情况。所以初始化0 行0列为0。

这里我将两个矩阵全部初始化为0增加了时间复杂度。

for (decltype(X.length()) i = 0; i < X.length(); i++) {for (decltype(X.length()) j = 0; j < Y.length(); j++) {c[i][j] = 0;s[i][j] = 0;}}

s与c矩阵的生成代码

for (decltype(X.length()) i = 1; i < X.length(); i++){for (decltype(Y.length()) j = 1; j < Y.length(); j++) {if (X[i] == Y[j] ){c[i][j] = c[i - 1][j - 1] + 1;   //相等 等于左上角元素s[i][j] = 1;           //回溯为左上回 且为子序列中元素}else if (c[i - 1][j] >= c[i][j - 1]) {    //不相等 且左边大于上面   等于左边元素c[i][j] = c[i - 1][j];   s[i][j] = 2;           //回溯为左回}else {c[i][j] = c[i][j - 1];   // 否则不相等且左边小于上面 等于上面元素s[i][j] = 3;         //回溯为上回}}}

回溯CLCS代码如下

void CLCS(int i,int j) {if (i==0||j==0){return;}if (s[i][j] == 1){CLCS(i - 1, j - 1);cout << X[i] << " ";}else if (s[i][j] == 2) {CLCS(i - 1, j);}else{CLCS(i, j - 1);}
}

输入的两个序列分别为:

0abcbdab
0bdcaba

使用文件重定向生成的输出文件为:

整体代码

void CLCS(int i, int j);int c[8][8]; //c计算并存储最大子序列
int s[8][8];    //s为回溯寻找子序列元素 1左上找并且为子序列元素 2上回溯 3左回溯
string X, Y;int main() {cin >> X >> Y;// X = 8, Y = 7for (decltype(X.length()) i = 0; i < X.length(); i++) {for (decltype(X.length()) j = 0; j < Y.length(); j++) {c[i][j] = 0;s[i][j] = 0;}}for (decltype(X.length()) i = 1; i < X.length(); i++){for (decltype(Y.length()) j = 1; j < Y.length(); j++) {if (X[i] == Y[j] ){c[i][j] = c[i - 1][j - 1] + 1; //相等 等于左上角元素s[i][j] = 1;           //回溯为左上回 且为子序列中元素}else if (c[i - 1][j] >= c[i][j - 1]) {    //不相等 且左边大于上面   等于左边元素c[i][j] = c[i - 1][j];   s[i][j] = 2;           //回溯为左回}else {c[i][j] = c[i][j - 1];   // 否则不相等且左边小于上面 等于上面元素s[i][j] = 3;         //回溯为上回}}}cout << "最大子序列矩阵:" << endl;for (decltype(X.length()) i = 0; i < X.length(); i++) {for (decltype(X.length()) j = 0; j < Y.length(); j++) {cout << c[i][j]<<" ";}cout << endl;}cout << "回溯矩阵:" << endl;for (decltype(X.length()) i = 0; i < X.length(); i++) {for (decltype(X.length()) j = 0; j < Y.length(); j++) {cout << s[i][j] << " ";}cout << endl;}CLCS( X.length() - 1, Y.length() - 1);system("pause");return 0;
}void CLCS(int i,int j) {if (i==0||j==0){return;}if (s[i][j] == 1){CLCS(i - 1, j - 1);cout << X[i] << " ";}else if (s[i][j] == 2) {CLCS(i - 1, j);}else{CLCS(i, j - 1);}
}

最长公共子序列-动态规划(C/C++)相关推荐

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

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

  2. C语言(CED)最长公共子序列----动态规划第一题

    一.动态规划算法与分治法的异同 相同点: A.二者均是将待求解的问题分成若干子问题来求解. B.二者在编写代码的时候,都要用到递归. 不同点: A.分治法求解的问题,在将问题分成若干子问题之后,其子问 ...

  3. 最长公共子序列动态规划c语言,动态规划----最长公共子序列(C++实现)

    最长公共子序列 题目描述:给定两个字符串s1 s2 - sn和t1 t2 - tm .求出这两个字符串的最长公共子序列的长度.字符串s1 s2 - sn的子序列指可以表示为 - { i1 < i ...

  4. 最长公共子序列--动态规划(C++)

    动态规划与分治方法类似,都是通过组合子问题来求解原问题.分治法将问题分为互不相交的子问题,递归的求解子问题,再将他们的解组合起来,求出原问题的解.相反的,动态规划用于子问题重叠的情况,即不同的子问题具 ...

  5. 116. Leetcode 1143. 最长公共子序列 (动态规划-子序列问题)

    步骤一.确定状态: 确定dp数组及下标含义 dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长 公共子序列为dp[i][j] 步骤二.推 ...

  6. nyoj36最长公共子序列 动态规划

    题目链接:http://115.159.40.116/problem_show.php?pid=4648 http://acm.nyist.net/JudgeOnline/problem.php?pi ...

  7. 最长公共子序列-动态规划-python

    题目描述 给定一个长度为 N 数组 a 和一个长度为 M 的数组 b. 请你求出它们的最长公共子序列长度为多少. 输入描述 输入第一行包含两个整数 N,M,分别表示数组 a 和 b 的长度. 第二行包 ...

  8. 夕拾算法进阶篇:15)最长公共子序列(动态规划DP)

    题目描述 给你一个序列X和另一个序列Z,当Z中的所有元素都在X中存在,并且在X中的下标顺序是严格递增的,那么就把Z叫做X的子序列. 例如:Z=<a,b,f,c>是序列X=<a,b,c ...

  9. bzoj 2423 [HAOI2010]最长公共子序列 动态规划

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

最新文章

  1. 七牛云删除图片接口_图片基本处理(imageView2)
  2. Android开发各类常见错误解决方案
  3. Docker常用命令(docker快捷键)海康docker命令 LY
  4. 影响程序员薪资的,从来不止是学历!
  5. nmon安装为什么重启mysql_Nmon的安装及使用
  6. 【转】无服务计算(Serverless Computing)核心知识
  7. 收购YY直播,百度重返高位的关键布局
  8. MySQL 性能分析 之 联合索引(复合索引)实践分析
  9. 大数据之-入门_大数据发展前景---大数据之hadoop工作笔记0005
  10. mac安装 配置 ant
  11. Alpine linux硬盘安装
  12. 初试小刀自我简历小程序
  13. 官方水晶报表 .NET 应用程序实例下载 (Visual Basic .NET)
  14. lzg_ad:XPE常见问题FAQ
  15. python怎样查找收盘价_如何在Python中从晨星获得调整后的收盘价?
  16. 计算机专业英语材料,计算机专业英语复习资料
  17. 不要告诉我你懂margin
  18. 工控机和服务器哪个稳定性高,简单分析工控机和服务器有什么不同
  19. 如何删除百度快照?百度快照是什么?百度快照优化是什么意思?
  20. 计算机二级Word第四套

热门文章

  1. C# 9.0 新功能一览!
  2. 面对疫情,AI 能做什么?
  3. 突发!程序员!快别闷头学Python了!
  4. 敲黑板划重点!「PV,UV流量预测算法大赛」明日结果提交最后1天!
  5. 评分 9.7!这本 Python 书彻底玩大了?程序员:满分!
  6. 想换行做 5G 的开发者到底该咋办?
  7. 电竞大数据平台 FunData 的系统架构演进
  8. 仅一年,近半加密货币的“ICO”项目已死
  9. PHP工程师最佳学习路线!【重磅推出】
  10. Kotlin 一统天下?Kotlin/Native 开始支持 iOS 和 Web 开发