[algorithm]求最长公共子序列问题

时间:2021-07-30 04:22:13

最直白方法:时间复杂度是O(n3), 空间复杂度是常数

reference:http://blog.csdn.net/monkeyandy/article/details/7957263

/**

** copyright@andy

** http://blog.csdn.net/MonkeyAndy

**/

首先介绍动态规划方法的相关知识

动态规划方法的基本思想:

分成若干个子问题,先求解子问题,然后根据子问题的解求得原问题的解。经分解得到的子问题往往不是互相独立的。可重复利用!

其核心思想就是分治,分治方法的特点是分解后的子问题相对独立,可以通过简单的合并算法得到原问题的解!

动态规划方法的应用对象:
优化问题:

  1. 一个优化问题可能有很多可行解,每个解都有一个求解代价,
  2. 我们希望选择一个具有最少代价的解。
  3. 一个优化问题可能有多个优化解。

动态规划方法:
当一个优化问题可分为多个子问题,子问题的解在构造上一级问题的求解过程中被重复使用。 这样可以节省计算时间与空间。

动态规划算法的步骤:

  1. 分析优化解的结构
  2. 递归地定义最优解的代价
  3. 自底向上地计算优化解的代价保存之,并获取构造最优解的信息。
  4. 根据计算优化解的代价,构造优化解
 
可用动态规划方法求解的问题必须满足的条件
     1. 具有优化子结构(Optimal substructure)
     如果一个问题的优化解包含了他的子问题的优化解,则称此问题具有优化结构。如,A1A2A3A4A5A6 的优化解是 (A1 ( A2A3)) ((A4A5)A6),其中A1 ( A2A3)和(A4A5)A6),分别是A1A2A3和A4A5A6的解。
        优化结构是应用动态规划方法的一个条件。是必要条件!
     2. 具有重叠子问题(Overlapping sub-problems)  
       如果递归算法求解一个优化问题时,需要反复求解相同的子问题,则称该优化问题具有重叠子问题。
       动态规划算法利用该性质,以求得的子问题的解保存后,自底向上地,重复利用子问题的解获得上级问题的解,节省空间开销和时间开销。
       如果不具备重叠子问题的性质动态规划方法的空间开销和时间开销很大。利用动态规划算法没有意义!
 
求最长公共子序列
 
 1. 子序列定义
    设x=(x1, x2, ... xm)是一个序列, z=(z1, z2, ... zm) 是x的一个子序列,如果存在1i1<i2<...<ik<m, 使xij=zj
    z=(z1, z2, ... zm)即是x=(x1, x2, ... xm)中删除一些元素以后得到的序列。

2.公共子序列定义
    Z是序列X与Y的公共子序列,如果Z是X的子序列且Z是Y的子序列。
     
    3.最长公共子序列问题(LCS)
    输入:X=(x1, x2, ... xn),Y=(y1, y2, ...ym)
    输出:X与Y的最长公共子序列Z

 
最长公共子序列结构分析
        定义. 设X=(x1 , x2 , ... xn) 是一个序列, Xi表示X的第i个前缀,即 Xi=(x1 , ... xi )。
        例.  X=(A,B,D,C,A),  X1=(A),  X2=(A,B),  X3=(A,B,D)
 
优化解的结构
    定理1(LCS的优化结构)设X=(x1 , ... xm), Y=(y1 , y2 , ... yn)是两个序列,Z=(z1 , z2 , ... zk) 是X与Y的LCS。下列结论成立:
  1. 如xm= yn, 则zk=xm=yn, Zk-1是Xm-1和Yn-1的LCS,即,LCS(X,Y)=LCS(Xm-1,Yn-1)+xm
  2. 若xm != yn,且zk!=xm,则Z是Xm-1和Y的LCS,即   LCS(X,Y)=LCS(Xm-1,Y)
  3. 若xm != yn , 且zk !=yn,则Z是X与Yn-1的LCS,即    LCS(X,Y)=LCS(X,Yn-1)
 
例如:
 
[algorithm]求最长公共子序列问题
 
 
建立求解LCS长度的递归方程
 
If xm= yn, xm属于X和Y的LCS,必须求解Xm-1和Yn-1的LCS。
If xm !=yn , 必须求解Xm-1和Y的LCS以及X和Yn-1 的LCS,长者是X和Y的LCS。C[i,j] 表示Xi与Yj的LCS的长度,则建立求解LCS长度的递归方程
 
[algorithm]求最长公共子序列问题
LCS长度的计算
    1.基本思想
       计算C[i,j] 需先计算C[i-1,j-1]、C[i,j-1]、C[i-1,j]
 
C[i-1,j-1] C[ i, j-1]
C[i-1,   j] C[  i,   j]

先计算出第0行与第0列,然后逐行计算。

 
[algorithm]求最长公共子序列问题

2.   算法

 
 
 
  1. /**
  2. *copyright@andy
  3. *date@ 2012/09/08
  4. * m : x的长度
  5. *  n : y的长度
  6. *  c : xi与yi的LCS的长度
  7. *  b : 用于标记xi和yi的关系
  8. **/
  9. void LCSLength( int m, int n, char *x, char *y int **c, Type **b )
  10. {
  11. int i, j;
  12. /*c 初始化*/
  13. for ( i=1; i<=m; i++) c[ 0 ][ i ]=0;
  14. for( j=1; j<=n, j++) c[ j ][0 ]=0;
  15. for ( i=1; i<=m; i++)
  16. for( j=1; j<=n, j++)
  17. {
  18. if(x[i]==y[j])  //xi = yj 时LCS 增1
  19. {
  20. c[ i ][ j ]=c[ i-1 ][ j-1]+1;
  21. b[ i ][ j ]='\'';
  22. }
  23. else if ( c[i-1][j] >= c[i][j-1]) //当xi ≠ yj时保存长子序列
  24. {
  25. c[ i ][ j ]=c[ i-1 ][ j];
  26. b[ i ][ j ]='|';
  27. }
  28. else
  29. {
  30. c[ i ][ j ]=c[ i ][ j-1];
  31. b[ i ][ j ]='--';
  32. }
  33. }
  34. }
 
3.   构造LCS算法
 
  1. /**
  2. *copyright@andy
  3. *date@ 2012/09/08
  4. * i : x的长度
  5. *  j : y的长度
  6. *  x : x字符串
  7. *  b : 用于标记xi和yi的关系
  8. **/
  9. void LCS( int i, int j, char *x, Type **b )
  10. {
  11. if ( i==0 || j==0) return;
  12. if (b[ i ][ j ] =='\'')//当xi = yj 时,输出xi ,并删除xi 和 yj ,之后在子序列中继续求解LCS
  13. {
  14. LCS(i-1, j-1, x, b);
  15. out<<x[ i ];
  16. }
  17. else if ( b[i][j] == '|')//当Xi-1 和 Yj 的LCS不小于Xi 和 Yj-1 的LCS 时
  18. LCS(i-1, j, x, b);    //在Xi-1 和 Yj中继续求解LCS;否则,在Xi 和 Yj-1 中继续求解LCS;
  19. else
  20. LCS( i, j-1, x, b);
  21. }

[algorithm]求最长公共子序列问题

 
LCSLength算法的时间复杂性O(mn)

[algorithm]求最长公共子序列问题的更多相关文章

  1. HDU 4681 string 求最长公共子序列的简单DP&plus;暴力枚举

    先预处理,用求最长公共子序列的DP顺着处理一遍,再逆着处理一遍. 再预处理串a和b中包含串c的子序列,当然,为了使这子序列尽可能短,会以c 串的第一个字符开始 ,c 串的最后一个字符结束 将这些起始位 ...

  2. HDU 1243 反恐训练营 (动态规划求最长公共子序列)

    反恐训练营 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  3. Java实现 LeetCode 583 两个字符串的删除操作(求最长公共子序列问题)

    583. 两个字符串的删除操作 给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符. 示例: 输入: &quot ...

  4. poj1458 求最长公共子序列 经典DP

    Common Subsequence Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 45763   Accepted: 18 ...

  5. codevs 1862 最长公共子序列(求最长公共子序列长度并统计最长公共子序列的个数)

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

  6. 动态规划求最长公共子序列(Longest Common Subsequence&comma; LCS)

    1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...

  7. 【dp】求最长公共子序列

    [题目描述] 一个给定序列的子序列是在该序列中删去若干元素后得到的序列.确切地说,若给定序列X=<x1,x2,…,xm>X=<x1,x2,…,xm>,则另一序列Z=<z1 ...

  8. Coincidence (动态规划求最长公共子序列)(王道)

    题目描述: Find a longest common subsequence of two strings. 输入: First and second line of each input case ...

  9. hdu 1159求最长公共子序列

    题目描述:给出两个字符串,求两个字符串的公共子序列(不是公共子串,不要求连续,但要符合在原字符串中的顺序) in: abcfbc abfcab programming contest abcd mnp ...

随机推荐

  1. DNS配置详解

    DNS简介在Linux中,域名服务(DNS)是由柏克莱网间名域(Berkeley Internet Name Domain——BIND)软件实现的.BIND是一个客户/服务系统,它的客户方面称为转换程 ...

  2. iOS 数据序列化,NSCoding&comma; NSCoder

    iOS可以利用NSKeyedArchiver类将对象序列化成NSData存储在磁盘上,但前提是该对象所属的类必须遵从NSCoding协议. NSCoding协议包含两个方法,要序列化的类必须实现它们 ...

  3. &lbrack;转载&rsqb; Linux进程关系

    在工作中, 主进程创建了子进程, 而子进程又创建了孙子进程, 然而子进程被莫名其妙的 kill 了, 结果主进程又启动了一个子进程, 子进程又尝试创建孙子进程, 但是这时候就有问题了, 因为孙子进程还 ...

  4. Unix domain sockets

    #server: SERVER_PATH = "/tmp/python_unix_socket_server" def run_unix_domain_socket_server( ...

  5. 如何在安裝SELinux的环境执行Quartus II

    (原創) 如何在安裝SELinux的環境執行Quartus II? (SOC) (Quartus II) (Linux) (RedHat) Abstract一般人安裝Linux時,也會同時安裝SELi ...

  6. ubuntu 下telnet 操纵memcache 实现

    memcache作为一款优秀的进程外缓存,常常被运用于高并发系统架构中.这里主要谈谈怎么通过telnet工具,查看memcache运行状况并对其key进行管理维护.假设memcache安装目录:/us ...

  7. Linux OpenCV读取视频失败,cvCreateFileCapture失败的解决

    背景: 近期想在嵌入式平台上开发QT+Opencv,无料PC机上编写的OpenCV程序老是打不开视频. 開始提示:OpenCV Error: Bad argument (Array should be ...

  8. MS Project 2007 工期、工时、资源、固定单位、固定工期、固定工时

    0. 基本概念 工期:指完成每项项目任务所经历的实际时间,及开始日期和结束时期之差.Project中,工期的默认单位是天. 工时:指将任务分配给资源后,每个资源执行任务的工作时间.Project中,工 ...

  9. css Modules 使用

    我目前常用的也就是引用类名,以及在需要修改某个ui组件原有的样式比较麻烦时,会使用 :global className{ color: red;}这样来修改... 更多请参考阮老师博客: http:/ ...

  10. C&num; Note16&colon; wpf window 中添加enter和双击事件

     一.添加回车(enter)事件 在C#编程时,有时希望通过按回车键,控件焦点就会自动从一个控件跳转到下一个控件进行操作. 以用户登录为例,当输入完用户名和密码后, 需要点击登录按钮,而登录按钮必须获 ...