首先,我们要搞清楚所谓最长公共子序列的概念。不然很容易把它和最长公共子串混淆,两者区别是:子序列只需要字符保持相对顺序,并不要求像公共字串那样组成字符还需连续。
问题:
给定两个字符串数组序列:

X[1...m] = {A, B, C, B, D, A, B}
Y[1...n] = {B, D, C, A, B, A}

求它们的最长公共子序列,我们可肉眼判断,这两个字符串数组序列的最长公共子序列长度为4.

“BDAB”
“BCAB”
“BCBA”

现在用代码解决这个问题,一般人比如说我最容易想到方法都是穷举法:
列出X的所有子序列,再在Y中找到和其匹配的最长子序列。
如果用穷举法解决,时间复杂度最多能达到O(n*2^m),也就是说,在一些特定场合比如校招面试,使用这种方法极易被pass。
再接来考虑递推
问题的核心就是找到X,Y的最长公共子序列,记为LCS(X,Y)。

如果xm = yn,则Ck = xm = yn 且 Ck-1是Xm-1和Yn-1的一个LCS
如果xm != yn 且 Ck != xm,则C是Xm-1和Y的一个LCS
如果xm != yn 且 Ck != yn,则C是X和Yn-1的一个LCS

public class 递归实现 {public static int Lcs(char x[],char y[],int i,int j) {if(i==0||j==0) {return 0;}else if(x[i]==y[j]) {return Lcs(x,y,i-1,j-1)+1;}else {return Max(Lcs(x,y,i-1,j),Lcs(x,y,i,j-1));}}private static int Max(int a,int b){if(a>b) {return a;}else {return b;}}
public static void main(String[] args) {//System.out.println((int)' ');String s1="ABCBDAB";char[] c1=new char[s1.length()+1];//带0字符的字符数组char[] t1=s1.toCharArray();c1[0]=(char)0;for(int i=1;i<t1.length;i++) {c1[i+1]=t1[i];}String s2="BDCABA";char[] c2=new char[s2.length()+1];//带0字符的字符数组char []t2=s2.toCharArray();c2[0]=(char)0;for(int i=1;i<t2.length;i++) {c2[i+1]=t2[i];}System.out.println(Lcs(c1,c2,c1.length-1,c2.length-1)) ;
}
}

但要是完全用递归求解,在整个二叉树的最有求解过程中,会有大量的重复调用。时间复杂度是指数级,并没有得到太大的优化。所以这里我们建议使用动态规划求解。
为了杜绝相关不必要重复步骤,我们选择用动态规划求解,通过备忘录或者说一张表来存放数据,避免重复的计算和调用,以空间换时间,同时本问题还符合动态规划的基本特征,求解最优子结构和重复子问题。

备忘录方法采用自顶向下方式,为每个解过的子问题建立了备忘录以备需要时查看,避免了相同子问题的重复求解

public class 备忘录法 {public static int Lcs(char x[],char y[],int i,int j,int bak[][]) {if(bak[i][j]!=-1) {return bak[i][j];}if(i==0||j==0) {return bak[i][j]=0;}else if(x[i]==y[j]) {return Lcs(x,y,i-1,j-1,bak)+1;}else {bak[i][j]=Max(Lcs(x,y,i-1,j,bak),Lcs(x,y,i,j-1,bak));}return bak[i][j];}private static int Max(int a,int b){if(a>b) {return a;}else {return b;}}
public static void main(String[] args) {//System.out.println((int)' ');String s1="ABCBDAB";char[] c1=new char[s1.length()+1];//带0字符的字符数组char[] t1=s1.toCharArray();c1[0]=(char)0;for(int i=1;i<t1.length;i++) {c1[i+1]=t1[i];}String s2="BDCABA";char[] c2=new char[s2.length()+1];//带0字符的字符数组char []t2=s2.toCharArray();c2[0]=(char)0;for(int i=1;i<t2.length;i++) {c2[i+1]=t2[i];}//初始化备忘录数组int [][]bak=new int[c1.length][c2.length];for(int i=0;i<c1.length;i++) {for(int j=0;j<c2.length;j++) {bak[i][j]=-1;}}System.out.println(Lcs(c1,c2,c1.length-1,c2.length-1,bak)) ;
}
}

备忘录法相比于递归以空间换时间,降低了时间复杂度,但占用内存会大大升高,并且它的时间复杂度相比于下面这种方法并不算太过优化。
动态规划—自底向上法:
采用自底向上方式,保存已求解的子问题,需要时取出,消除对某些子问题的重复求解.

import java.util.Scanner;public class 自底向上 {public static int Lcs(char x[],char y[],int i,int j,int bak[][]) {for(int ii=0;ii<=i;ii++) {for(int jj=0;jj<=j;jj++) {if(ii==0||jj==0) {bak[ii][jj]=0;}else if(x[ii]==y[jj]) {bak[ii][jj]= bak[ii-1][jj-1]+1;}else {bak[ii][jj]=Max(bak[ii-1][jj],bak[ii][jj-1]);}}}return bak[i][j];}private static int Max(int a,int b){if(a>b) {return a;}else {return b;}}
public static void main(String[] args) {Scanner s=new Scanner(System.in);//System.out.println((int)' ');String s1=s.nextLine();char[] c1=new char[s1.length()+1];//带0字符的字符数组char[] t1=s1.toCharArray();c1[0]=(char)0;for(int i=1;i<t1.length;i++) {c1[i+1]=t1[i];}String s2=s.nextLine();char[] c2=new char[s2.length()+1];//带0字符的字符数组char []t2=s2.toCharArray();c2[0]=(char)0;for(int i=1;i<t2.length;i++) {c2[i+1]=t2[i];}int [][]bak=new int[c1.length][c2.length];System.out.println(Lcs(c1,c2,c1.length-1,c2.length-1,bak)) ;
}
}

【谈谈】动态规划——求最长公共子序列相关推荐

  1. Java动态规划求最长公共子序列(LCS)

    最长公共子序列(LCS) 定义:在序列X和序列Y中同时出现的元素,按照脚标从小到大排列的这样的序列.         String x = "ABCBDABGGGTT";      ...

  2. Algorithm:C++/python语言实现之求旋转数组最小值、求零子数组、求最长公共子序列和最长公共子串、求LCS与字符串编辑距离

    Algorithm:C++/python语言实现之求旋转数组最小值.求零子数组.求最长公共子序列和最长公共子串.求LCS与字符串编辑距离 目录 一.求旋转数组最小值 1.分析问题 2.解决思路 二.求 ...

  3. 实验二 动态规划算法 最长公共子序列问题

    基本题一:最长公共子序列问题 一.实验目的与要求 1.熟悉最长公共子序列问题的算法: 2.初步掌握动态规划算法: 二.实验题 若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,z ...

  4. 动态规划解决最长公共子序列

    动态规划解决最长公共子序列 问题描述 给定两个序列,例如 X = "ABCBDAB".Y = "BDCABA",求它们的最长公共子序列的长度. 递归关系 c[i ...

  5. 求最长公共子序列长度

    求两个字符串的公共子序列 1.求最长公共子序列(子序列可以不连续) 这是一道动态规划题,设二维数组dp[i][j],dp[i][j]表示a串前i个字符(包括第i个)与b串前j个字符(包括第j个)所有的 ...

  6. 动态规划解最长公共子序列(LCS)(附详细填表过程)

    目录 相关概念 子序列形式化定义: 公共子序列定义: 最长公共子序列(以下简称LCS): 方法 蛮力法求解最长公共子序列: 动态规划求解最长公共子序列: 分析规律: 做法: 伪代码: 下面演示下c数组 ...

  7. 动态规划篇——最长公共子序列(c++)

    引言:最长公共子序列属于动态规划的基础篇,由字符串的最长公共最序列可以引出很多的问题. 最长子序列详细讲解以及练习题目 需要详细讲解教程的可以观看上面链接的文章,以下是自己做的简单的概括. 一.何为最 ...

  8. 动态规划之——最长公共子序列(nyoj36)

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

  9. 2192-Zipper 求最长公共子序列的解题报告

    主要的思考方向就是求dp里面的最长公共子序列.至于字符串本身的判别并不是重点. 根据网上poj的分类,这个题是dp求最长公共子序列,其实用暴力的方法也能通过.暴力的方法比较简单就不多说了.主要讲讲dp ...

最新文章

  1. UIPickerView和UIDataPicker
  2. Visual Studio将原生支持WSL 2
  3. 免费算力提供!这个含YOLOv3算法讲解的深度学习课程来了
  4. 数学知识点回顾(三)
  5. 现代软件工程个人作业进度
  6. Nginx 的 server_names_hash_bucket_size 问题
  7. 新手进阶:巧用 macOS 帮助菜单?
  8. 如何为自己的在线办公软件 ONLYOFFICE Docs 服务器的字体库添加字体
  9. 航模入门经典教材:航空模型教材
  10. 十五届恩智浦智能车-四十天做四轮-调车日记
  11. Win7环境下VS2015安装+CUDA 10.0安装配置教程以及安装环境时遇到的一些问题
  12. python模拟别人说话的声音_现在你可以通过深度学习用别人的声音来说话了
  13. matlab制作科学计算器,基于MATLAB科学计算器
  14. 首次使用计算机 鼠标没反应,电脑鼠标没反应是怎么回事
  15. 积极心理学第十九课 如何让爱情天长地久
  16. 大连交通大学IPTV使用方法
  17. 基于ESP8266的STM32物联网开发板
  18. CFileDialog 异常问题
  19. backtrack5 初步配置
  20. c语言列车信息管理系统,C语言火车票信息管理系统.doc

热门文章

  1. altera fpga 型号说明_ALTERA的FPGA命名规则
  2. WCP人员管理之添加人员
  3. Obsidian 图片显示问题
  4. 英文产品网站的搜索引擎推广
  5. 使用面膜过敏现象原因
  6. 手把手看如何制作本地yun源
  7. html5css游戏,HTML5/CSS3 迷你赛车游戏
  8. 不忘初心,方得始终——NOIP2016前的感悟
  9. html5充值页面(Vue)
  10. matlab降噪报告,基于matlab主动降噪实验.docx