算法介绍

动态规划:

动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的(自底向上求解,底层的解可作为上层解的基础 )。

问题实例

问题描述:

题目:
给定两个字符串,求解这两个字符串的最长公共子序列(Longest Common Sequence)。
比如字符串1:BDCABA;字符串2:ABCBDAB
则这两个字符串的最长公共子序列长度为4,最长公共子序列是:BCBA

问题分析

对于动态规划的问题我们一般使用数组记录小的分组得到的结果。在该题中我们利用循环比较两条序列的每个字符,分三种情况。
举个小例子:
(S1={1,3,4,5,6,7,7,8}和S2={3,5,7,4,8,6,7,8,2})

假如S1的最后一个元素 与 S2的最后一个元素相等,那么S1和S2的LCS就等于 {S1减去最后一个元素} 与 {S2减去最后一个元素} 的 LCS 再加上 S1和S2相等的最后一个元素。

假如S1的最后一个元素 与 S2的最后一个元素不等(本例子就是属于这种情况),那么S1和S2的LCS就等于 : {S1减去最后一个元素} 与 S2 的LCS, {S2减去最后一个元素} 与 S1 的LCS 中的最大的那个序列。

数学公式如下:

伪代码:

①设数组c[][] 和数组b[][],c[][] 记录此时最长公共子序列的长度,b[][] 记录产生最长公共子序列的过程。
②利用循环遍历比较每个字符,当字符相同时,此时最长公共子序列加一,记录过程为1;当c [i-1] [j] >= c [i] [j-1] 时,c [i] [j] = c [i-1] [j] ,记录过程为2;当c [i-1] [j] < c [i] [j-1] 时,相反,记录为3。
③通过b [i] [j] 倒推出S1和S2的LCS,并记录下标。
④打印输出,结束。

代码:

#include <iostream>
#include <string>using namespace std;
void LCS(string s1,string s2)
{int m=s1.length()+1;int n=s2.length()+1;int **c;int **b;c=new int* [m];b=new int* [m];for(int i=0;i<m;i++){c[i]=new int [n];b[i]=new int [n];for(int j=0;j<n;j++)b[i][j]=0;}for(int i=0;i<m;i++)c[i][0]=0;for(int i=0;i<n;i++)c[0][i]=0;for(int i=0;i<m-1;i++){for(int j=0;j<n-1;j++){if(s1[i]==s2[j]){c[i+1][j+1]=c[i][j]+1;b[i+1][j+1]=1;          //1表示箭头为  左上}else if(c[i][j+1]>=c[i+1][j]){c[i+1][j+1]=c[i][j+1];b[i+1][j+1]=2;          //2表示箭头向  上}else{c[i+1][j+1]=c[i+1][j];b[i+1][j+1]=3;          //3表示箭头向  左}}}for(int i=0;i<m;i++)                //输出c数组{for(int j=0;j<n;j++){cout<<c[i][j]<<' ';}cout<<endl;}cout<<endl;for(int i=0;i<m;i++)                //输出b数组{for(int j=0;j<n;j++){cout<<b[i][j]<<' ';}cout<<endl;}char A[20];int num=0;int x=m-1,y=n-1;while(x>=0&&y>=0&&b[x][y]!=0){if(b[x][y]==1){x--;y--;A[num]=s1[x];num++;}else if(b[x][y]==2){x--;}else if(b[x][y]==3){y--;}}cout<<endl<<"最长公共子序列为:";for(int i=num-1;i>=0;i--){cout<<A[i];}cout<<endl<<"长度为:"<<c[m-1][n-1]<<endl;
//    stack<char> same;                   //存LCS字符
//    stack<int> same1,same2;             //存LCS字符在字符串1和字符串2中对应的下标,方便显示出来
//    for(int i = m-1,j = n-1;i >= 0 && j >= 0; )
//    {//        if(b[i][j] == 1)
//        {//            i--;
//            j--;
//            same.push(s1[i]);
//            same1.push(i);
//            same2.push(j);
//        }
//        else if(b[i][j] == 2)
//                i--;
//        else
//                j--;
//    }
//
//    cout<<endl<<"最长公共子序列为:";
//    while(!same.empty())
//    {//        cout<<same.top();
//        same.pop();
//    }
//    cout<<endl<<"长度为:"<<c[m-1][n-1]<<endl;
}
int main()
{string s1="BDCABA";string s2="ABCBDAB";LCS(s1,s2);return 0;
}

结果:

解决本题的关键是如何利用b [i] [j] 逆序找到相应的字符。在本题中,如果b [i] [j] 为1,记录该字符下标,如果b [i] [j] 为2,向上平移1行,如果b [i] [j] 为3,向左平移一行,直到达到边界(b [i] [j] 为0时)。

记录整理一些学习中的问题,如果有不恰当和错误的地方,欢迎批评指正~

算法设计-动态规划——最长公共子序列相关推荐

  1. 算法设计 - LCS 最长公共子序列最长公共子串 LIS 最长递增子序列

    出处 http://segmentfault.com/blog/exploring/ 本章讲解: 1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度: 2. 与之类似但不 ...

  2. 算法:动态规划——最长公共子序列

    文章目录 一.动态规划概念 1. 动态规划步骤 最长公共子序列问题 题目 示例 分析 代码(递归) 查表 打印最长公共子序列 一.动态规划概念 动态规划算法与分治法类似,其基本思想也是将待求解问题分解 ...

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

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

  4. 动态规划—最长公共子序列问题 HDU-1159 Common Subsequence

    动态规划-最长公共子序列问题 Common Subsequence [ HDU - 1159 ] A subsequence of a given sequence is the given sequ ...

  5. 详解动态规划最长公共子序列--JavaScript实现

    前面两篇我们讲解了01背包问题和最少硬币找零问题.这篇将介绍另一个经典的动态规划问题--最长公共子序列.如果没看过前两篇,可点击下面链接. 详解动态规划最少硬币找零问题--JavaScript实现 详 ...

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

    动态规划1--最长公共子序列 一.动态规划 经常会遇到复杂问题不能简单地分解成几个子问题,而会分解出一系列的子问题.简单地采用把大问题分解成子问题,并 综合子问题的解导出大问题的解的方法,问题求解耗时 ...

  7. 最长公共子序列php,动态规划(最长公共子序列LCS)

    概念 求解决策过程最优化的结果 (可能有多个) 把多阶段过程转化为一系列单阶段过程,利用各阶段之间的关系,逐个求解 计算过程中会把结果都记录下,最终结果在记录中找到. 举例 求两个字符串的最长公共子序 ...

  8. 动态规划——最长公共子序列(算法设计课题)

    问题描述: 若给定序列X={x1,x2,-,xm},则另一序列Z={z1,z2,-,zk},是X的子序列是指存在一个严格递增下标序列{i1,i2,-,ik}使得对于所有j=1,2,-,k有:zj=xi ...

  9. c语言最长公共子序列,算法设计与分析/动态规划——最长公共子序列LCS及模板...

    这位大佬写的对理解DP也很有帮助,我就直接摘抄过来了,代码部分来自我做过的题 一,问题描述 给定两个字符串,求解这两个字符串的最长公共子序列(Longest Common Sequence).比如字符 ...

最新文章

  1. ubuntu apt-get停在了“configuring ttf-mscorefonts-installer”
  2. Gibbs sampling
  3. 一个把图片保存到SQL数据库的工具
  4. 栈的应用--迷宫问题
  5. RabbitMQ消息确认机制
  6. 区块链中的密码学,使用ABE结合区块链
  7. 在Windows和Azure中使用加密证书提高web.config的安全性
  8. java只读xml文件头_为了生成只读的接口和xml,并命名结尾为MapperR.java和MapperR.xml...
  9. 【Android】【移动应用开发】基础案列
  10. siamfc-pytorch代码讲解(二):trainsiamfc
  11. 几种码农使用的等宽字体比较——让自己的眼睛爽起来!
  12. 围棋智能机器人阿法狗,阿尔法狗机器人围棋
  13. 玲珑学院-1014-Absolute Defeat【思维】
  14. 用opencv和python读取医学图片:mha
  15. android友盟统计,RN集成友盟统计(Android)
  16. 2.1用户界面设计的八项黄金法则
  17. Java 14:JDK 14进入GA时的所有新功能
  18. 【洛谷】P2006 赵神牛的游戏 c++
  19. Android-自定义UI模板
  20. 计算机的风扇参数,电脑静音高效有诀窍 选购对风扇不可少

热门文章

  1. 【Web技术】1480- 呀!原来这就是前端监控系统
  2. float计算丢精度_Float和double丢失精度问题及解决方案
  3. 当React开发者初次走进React-Native的世界
  4. Web项目之管理系统
  5. 计算机科学家蒂姆,“万维网之父”蒂姆·伯纳斯·李的科学家精神
  6. document.documentElement.clientWidth
  7. 插入利用Mybatis数据库时,插不进去或者删除不了(无法更新)数据解决方案
  8. 2022年最新河北水利水电施工安全员模拟试题题库及答案
  9. 无线通信协议CSMA/CA的简单总结
  10. POJ 3928 hdu 2492 Uva1428 PingPong 【树状数组】