给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的)。

比如两个串为:
abcicba
abdkscab
ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最长的子序列。
Input
第1行:字符串A
第2行:字符串B
(A,B的长度 <= 1000)
Output
输出最长的子序列,如果有多个,随意输出1个。
Input示例
abcicba
abdkscab
Output示例
abca

问题定义• 子序列– X=(A, B, C, B, D, B)– Z=(B, C, D, B)是X的子序例– W=(B, D, A)不是X的子序例• 公共子序列–Z是序列X与Y的公共子序列如果Z是X的子序也是Y的子序列。最长公共子序列(LCS)问题输入:X = (x1,x2,...,xn),Y =(y1,y2,...ym)输出:Z = X与Y的最长公共子序列最长公共子序列结构分析• 第i前缀– 设X=(x1, x2, ..., xn)是一个序列,X的第i前缀Xi是一个序列,定义为Xi=(x1, ..., xi )例. X=(A, B, D, C, A), X1=(A), X2=(A, B), X3=(A,B, D)优化子结构定理1(优化子结构)设X=(x1, ..., xm)、Y=(y1, ..., yn) 是两个序列,Z=(z1, ..., zk)是X与Y的LCS,我们有:⑴ 如果xm=yn, 则zk=xm=yn, Zk-1是Xm-1和Yn-1的LCS,即,LCSXY = LCSXm-1Yn-1+ <xm=yn>.⑵ 如果xm.yn,且zk.xm,则Z是Xm-1和Y的LCS,即 LCSXY= LCSXm-1Y⑶ 如果xm.yn,且zk.yn,则Z是X与Yn-1的LCS,即 LCSXY= LCSXYn-1证明:⑴. X=<x1, …, xm-1, xm>, Y=<y1, …, yn-1, xm>,则LCSXY = LCSXm-1Yn-1+ <xm=yn>.设zkxm,则可加xm=yn到Z,得到一个长为k+1的X与Y的公共序列,与Z是X和Y的LCS矛盾。于是zk=xm=yn。现在证明Zk-1是Xm-1与Yn-1的LCS。显然Zk-1是Xm-1与Yn-1的公共序列。我们需要证明Zk-1是LCS。设不然,则存在Xm-1与Yn-1的公共子序列W,W的长大于k-1。增加xm=yn到W,我们得到一个长大于k的X与Y的公共序列,与Z是LCS矛盾。于是,Zk-1是Xm-1与Yn-1的LCS.⑵ X=<x1, …, xm-1, xm>, Y=<y1, …, yn-1, yn>,xmyn,zkxm,则 LCSXY= LCSXm-1Y由于zkxm,Z是Xm-1与Y的公共子序列。我们来证Z是Xm-1与Y的LCS。设Xm-1与Y有一个公共子序列W,W的长大于k, 则W也是X与Y 的公共子序列,与Z是LCS矛盾。⑶ 同⑵可证。X和Y的LCS的优化解结构为LCSXY=LCSXm-1Yn-1+ <xm=yn> if xm=ynLCSXY=LCSXm-1Y if xm≠yn, zk≠xmLCSXY=LCSXYn-1 if xm≠yn, zk≠yn

建立LCS长度的递归方程• C[i, j] = Xi与Yj 的LCS的长度• LCS长度的递归方程C[i, j] = 0 if i=0 或 j=0C[i, j] = C[i-1, j-1] + 1 if i, j>0 且 xi = yjC[i, j] = Max(C[i, j-1], C[i-1, j]) if i, j>0 且 xi ≠ yj

自底向上计算LCS的长度

计算LCS长度的算法– 数据结构C[0:m,0:n]: C[i,j]是Xi与Yj的LCS的长度B[1:m,1:n]: B[i,j] 是指针, 指向计算C[i,j]时所选择的子问题的优化解所对应的C表的表项

LCS-length(X, Y)m←length(X);n←length(Y);For i←1 To m Do C[i,0]←0;For j←1 To n Do C[0,j]←0;For i←1 To m DoFor j←1 To n DoIf xi = yjThen C[i,j]←C[i-1,j-1]+1;B[i,j]←“↖”;Else If C[i-1,j]≥C[i,j-1]Then C[i,j]≥C[i-1,j]; B[i,j]←“↑”;Else C[i,j]≥C[i,j-1]; B[i,j]←“←”;Return C and B.构造优化解• 基本思想– 从B[m, n]开始按指针搜索– 若B[i, j]=“↖”,则xi=yj是LCS的一个元素– 如此找到的“LCS”是X与Y的LCSPrint-LCS(B, X, i, j)IF i=0 or j=0 THEN Return;IF B[i, j]=“↖”THEN Print-LCS(B, X, i-1, j-1);Print xi;ELSE If B[i, j]=“↑”THEN Print-LCS(B, X, i-1, j);ELSE Print-LCS(B, X, i, j-1).

Print-LCS(B, X, length(X), length(Y))可打印出X与Y的LCS。
 1      /*功能:计算最优值
 2       *参数:
 3       *        x:字符串x  X:字符串x最大长度
 4       *        y:字符串y   Y:字符串y最大长度
 5       *        b:标志数组
 6       *        xlen:字符串x的长度
 7       *        ylen:字符串y的长度
 8       *返回值:最长公共子序列的长度
 9       *
10       */
11      int Lcs_Length(string x, string y, int b[][Y+1],int xlen,int ylen)
12      {
13          int i = 0;
14          int j = 0;
15
16          int c[X+1][Y+1];
17          for (i = 0; i<=xlen; i++)
18          {
19              c[i][0]=0;
20          }
21          for (i = 0; i <= ylen; i++ )
22          {
23              c[0][i]=0;
24          }
25          for (i = 1; i <= xlen; i++)
26          {
27
28              for (j = 1; j <= ylen; j++)
29              {
30                  if (x[i - 1] == y[j - 1])
31                  {
32                      c[i][j] = c[i-1][j-1]+1;
33                      b[i][j] = 1;
34                  }
35                  else
36                      if (c[i-1][j] > c[i][j-1])
37                      {
38                          c[i][j] = c[i-1][j];
39                          b[i][j] = 2;
40                      }
41                      else
42                          if(c[i-1][j] <= c[i][j-1])
43                          {
44                              c[i][j] = c[i][j-1];
45                              b[i][j] = 3;
46                          }
47
48              }
49          }
50
51          cout << "计算最优值效果图如下所示:" << endl;
52          for(i = 1; i <= xlen; i++)
53          {
54              for(j = 1; j < ylen; j++)
55              {
56                  cout << c[i][j] << " ";
57              }
58              cout << endl;
59          }
60
61          return c[xlen][ylen];
62      }

完整代码

    //只能打印一个最长公共子序列#include <iostream>using namespace std;const int X = 1000, Y = 1000;        //串的最大长度char result[X+1];                    //用于保存结果int count=0;                        //用于保存公共最长公共子串的个数int c[X+1][Y+1];int b[X + 1][Y + 1];/*功能:计算最优值*参数:*        x:字符串x*        y:字符串y*        b:标志数组*        xlen:字符串x的长度*        ylen:字符串y的长度*返回值:最长公共子序列的长度**/int Lcs_Length(string x, string y, int b[][Y+1],int xlen,int ylen){int i = 0;int j = 0;//int c[X+1][Y+1];for (i = 0; i<=xlen; i++){c[i][0]=0;}for (i = 0; i <= ylen; i++ ){c[0][i]=0;}for (i = 1; i <= xlen; i++){for (j = 1; j <= ylen; j++){if (x[i - 1] == y[j - 1]){c[i][j] = c[i-1][j-1]+1;b[i][j] = 1;}elseif (c[i-1][j] > c[i][j-1]){c[i][j] = c[i-1][j];b[i][j] = 2;}elseif(c[i-1][j] <= c[i][j-1]){c[i][j] = c[i][j-1];b[i][j] = 3;}}}/*cout << "计算最优值效果图如下所示:" << endl;for(i = 1; i <= xlen; i++){for(j = 1; j < ylen; j++){cout << c[i][j] << " ";}cout << endl;}*/return c[xlen][ylen];}void Display_Lcs(int i, int j, string x, int b[][Y+1],int current_Len){if (i ==0 || j==0){return;}if(b[i][j]== 1){current_Len--;result[current_Len]=x[i- 1];Display_Lcs(i-1, j-1, x, b, current_Len);}else{if(b[i][j] == 2){Display_Lcs(i-1, j, x, b, current_Len);}else{if(b[i][j]==3){Display_Lcs(i, j-1, x, b, current_Len);}else{Display_Lcs(i-1,j,x,b, current_Len);}}}}int main(int argc, char* argv[]){string x;string y;cin>>x>>y;int xlen = x.length();int ylen = y.length();//int b[X + 1][Y + 1];int lcs_max_len = Lcs_Length( x, y, b, xlen,ylen );//cout << lcs_max_len << endl;Display_Lcs( xlen, ylen, x, b, lcs_max_len );//打印结果如下所示for(int i = 0; i < lcs_max_len; i++){cout << result[i];}cout << endl;return 0;}

算法复杂性:

• 时间复杂性
– 计算代价的时间
• (i, j)两层循环,i循环m步, j循环n步
• O(mn)
– 构造最优解的时间: O(m+n)
– 总时间复杂性为:O(mn)
• 空降复杂性
– 使用数组C和B
– 需要空间O(mn)

转载于:https://www.cnblogs.com/KID-XiaoYuan/p/6349131.html

【51NOD】1006 最长公共子序列Lcs(动态规划)相关推荐

  1. 51NOD 1006 最长公共子序列 Lcs 动态规划 DP 模板题 板子

    给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为: abcicba abdkscab ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最 ...

  2. 51nod题解 1006 最长公共子序列LCS

    题目 #include<iostream> #include<cstring> #include<cstdio> using namespace std;char ...

  3. [Leetcode][第1143题][JAVA][最长公共子序列][LCS][动态规划]

    [问题描述][中等] [解答思路] 时间复杂度:O(N^2) 空间复杂度:O(N^2) class Solution {public int longestCommonSubsequence(Stri ...

  4. 51 nod 1006 最长公共子序列Lcs

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1006 参考博客 :http://blog.csdn.net/yysdsy ...

  5. 动态规划算法解最长公共子序列LCS问题

    动态规划算法解LCS问题 作者 July 二零一零年十二月三十一日 本文参考:微软面试100题系列V0.1版第19.56题.算法导论.维基百科. 第一部分.什么是动态规划算法 ok,咱们先来了解下什么 ...

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

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

  7. 算法导论-----最长公共子序列LCS(动态规划)

    目录 一.概念梳理 二.最长公共子序列解决方案 方案1:蛮力搜索策略 方案2:动态规划策略 三.C代码实现 实现1 实现2(空间优化) 一.概念梳理   1. 子序列(subsequence): 一个 ...

  8. 动态规划表格法解决最长公共子序列(LCS)问题

    3.5 最长公共子序列(LCS) 前言:图片是博主自己画的,转载请注明出处哦 3.5.1 问题描述 最长公共子序列(Longest Common Subseuence,LCS)问题:给定两个字符串,求 ...

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

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

最新文章

  1. 每日一皮:这真的是亲爹吗...
  2. python request-Python之request模块-基础用法
  3. UVA-10714 Ants---蚂蚁模拟
  4. 团队文化之表扬和批评
  5. python如何使用图片做背景_用Python批量给照片换底色,基于opencv模块
  6. FXK Javascript
  7. (转).gitignore详解
  8. python 银行工作_Python:银行系统实战(一)
  9. dayjs​​​​​​​文档
  10. c语言简短的泡沫排序法编程,冒泡排序--简单(c语言)
  11. 编译linux内核适用的编译器,编译Linux内核时,CC,LD和CC [M]输出的代码是什么?...
  12. 如何删除多余系统引导项
  13. java struts1_struts1.x
  14. 海底捞:今年年底前将关停约300家经营未达预期门店
  15. C语言中结构体内存存储方式
  16. vue3,vite2,json数据通过拼接显示链接src
  17. linux系统修改只读文件权限如(etc/hosts)文件
  18. Security+ 学习笔记52 风险管理
  19. 数据分析师—Excel技巧篇
  20. 出售,2012年世界末日诺亚舟船票,绝密

热门文章

  1. 人工智能 | 元学习与图神经网络逻辑推导与理解
  2. Github | 标星20k+ Facebook 开源高效词表征学习库fastText
  3. DWA论文解析(CurvatureVelovityMethod)(3)
  4. 展示面-网络安全相关学习总结
  5. mysql 如何按时间备份_如何定时备份mysql数据库
  6. 通信接口主要的5种类型_5种常见的住宅建筑结构类型,你真的了解吗?
  7. dijkstra标号法表格_标号法求最短路径例题详解.ppt
  8. Android开发实战一之搭建开发环境-附测试实例(已亲测)
  9. cpout引脚是干什么的_FPGA中差分信号的定义和使用(一)
  10. Java基础---学Java怎么能不了解多线程---Lambda表达式