最长公共子串问题(动态规划)

问题描述

1.最长公共子序列的结构

解释:

(1)X和Y的末尾元素相同则,公共子串一定包含末尾元素,所以公共子串是X和Y的公共子串
(2)X和Y的末尾元素不同,Y末尾元素和最长公共子序列的末尾元素相同,说明X要遍历全部,而X末尾元素无需考虑,所以最长公共子序列为X和Y的前M-1个元素
(3)X和Y的末尾元素不同,X末尾元素和最长公共子序列的末尾元素相同,说明X要遍历全部,而Y末尾元素无需考虑,所以最长公共子序列为X和Y的前N-1个元素


2.子问题的递归结构


3.计算最优值

4.代码实现

int lcs(int m, int n, string x, string y, int** c, int** b)
{
//m为字符串x的长度 n为字符串y的长度//c为c[i][j]数组,表示i-1长度x,j-1长度的y的最长公共子序列的长度//b记录路劲,1为x,y都增长,2为x增长,3为y增长//初始化    如何一个字符串长度为0,则公共子串长度为0int i, j;for (i = 0; i <= m; i++) {c[i][0] = 0;//y为空串b[i][0] = 0;}for (i = 0; i <= n; i++){c[0][i] = 0;//x为空串b[0][i] = 0;}for (i = 1; i <= m; i++) {for (j = 1; j <= n; j++) {if (x[i - 1] == y[j - 1])//第一种情况,末尾相同{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{c[i][j] = c[i][j - 1];//第三种情况b[i][j] = 3;}}}for (i = 0; i <= m; i++)//输出c矩阵查看{for (j = 0; j <=n; j++) {cout << c[i][j] << ' ';}cout << endl;}return c[m - 1][n - 1];
}

测试样例

int main()
{int** c, **b;c = new int* [10];b = new int* [10];for (int i = 0; i < 10; i++){c[i] = new int[10]{};b[i] = new int[10]{};}string x = "abcbdabe";string y = "bdcabae";cout << lcs(8, 7, x, y, c, b);}

测试结果

这里因为还有记录路径,所以写了3种情况,如果不记录路径的话只需要2种情况相同和不同,相同的情况在前一种基础上加1,不同的情况就是x小,y小2种情况中取较大者,修改关键代码图下

for (i = 1; i < m; i++) {for (j = 1; j < n; j++) {if (x[i - 1] == y[j - 1]){c[i][j] = c[i-1][j-1]+1;}else{c[i][j] = max(c[i-1][j],c[i][j-1]);}}}

求出路径


上面的b矩阵记录了数组xy不同长度下的情况。我们知道情况1是x和y字母相同c[i][j] = c[i - 1][j - 1]+1,x,y都增加,符合公共子串。2 是c[i][j] = c[i - 1][j],字符串x的长度增加,是向下。3是c[i][j] = c[i][j - 1],是y字符串增加,向右。所以我们只需要从i=1,j=1开始,按照遇到1 执行i–;j–。遇到2执行i–;遇到3执行j–;遍历完矩阵b就可以得到最终的最长公共子序列

完整代码

int lcs(int m, int n, string x, string y, int** c, int** b)
{//m为字符串x的长度    n为字符串y的长度//c为c[i][j]数组,表示i-1长度x,j-1长度的y的最长公共子序列的长度//b记录路劲,1为x,y都增长,2为x增长,3为y增长//初始化    如何一个字符串长度为0,则公共子串长度为0int i, j;for (i = 0; i <= m; i++) {c[i][0] = 0;//y为空串b[i][0] = 0;}for (i = 0; i <= n; i++){c[0][i] = 0;//x为空串b[0][i] = 0;}for (i = 1; i <= m; i++) {for (j = 1; j <= n; j++) {if (x[i - 1] == y[j - 1])//第一种情况,末尾相同{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{c[i][j] = c[i][j - 1];//第三种情况b[i][j] = 3;}}}for (i = 0; i <= m; i++)//输出c矩阵查看{for (j = 0; j <=n; j++) {cout << c[i][j] << ' ';}cout << endl;}cout << endl;for (i = 0; i <= m; i++)//输出c矩阵查看{for (j = 0; j <= n; j++) {cout << b[i][j] << ' ';}cout << endl;}cout << endl;i--; j--;while (i > 0 && j > 0){if (b[i][j] == 1) { cout << x[i-1]; i--; j--; }else if (b[i][j] == 2) { i--; }else { j--; }}cout << endl;return c[m - 1][n - 1];
}

结果

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最新文章

  1. catia怎么创建约束快捷键_答疑 | CATIA结构树无法显示怎么办?
  2. IDEA2020如何设置全局maven路径
  3. 老年机按键串号_2019年最适合买的老人机——AGM M5,4G全网通+支持微信
  4. Linux思维导图整理,你确定不收藏?
  5. IE 域组策略对服务器无效的原因
  6. mybatis-嵌套(关联)查询/ N+1 / 延迟加载
  7. linux测试函数耗时tick数,C语言中怎样测验函数执行时间
  8. go语言和php哪个建站好,从0开始Go语言,用Golang搭建网站
  9. MySQL字符集 GBK、GB2312、UTF8区别 解决 MYSQL中文乱码问题
  10. 略谈人工智能算法的缺点
  11. sqlite3_get_table()
  12. android+p开机动画,android开机动画[转]
  13. c语言函数定义的语法格式,C语言函数 -C语言函数定义的语法格式
  14. 【神器】yololib 飘云修改版 -- 给iOS APP 添加导入表注入--你懂的
  15. 3D建模师和3D动画师哪个职业前景好些?
  16. zabbix代理服务器配置
  17. ZZULIOJ-1088: 手机短号 (多实例)(Java)
  18. python抓取微信文件_fiddle python抓取微信公众号文章
  19. SpringBoot--SpringBoot 读取Properties文件(结合JDBC)
  20. QQ跳转加好友、加QQ群链接代码生成制作

热门文章

  1. 【券商报告】电子元器件行业MLCC专题:电动化、智能化、5G驱动行业景气持续上行,国产替代加速——附下载链接
  2. 一个有趣的网站,开发同事要看的577个网站,小牛导航(super-nb)一站给聚合了
  3. linux停用用户账号的命令,Linux 系统中用户/组账号的基本常用命令备忘录
  4. ajax请求设置同步,ajax 设置同步
  5. teamview批量管理连接电脑
  6. 反应式编程之flux concatmap
  7. Controller层和Service层具体区分
  8. 信息熵、交叉熵、KL散度公式的简单理解
  9. 2020大学生网络安全知识总决赛 NISP一级模拟题(09)
  10. 再看数学——丘成桐:数学的内容、方法和意义