长公共子序列(longest common sequence)
最长公共子串(longest common substring)
子序列:一个给定的序列的子序列,将给定序列中零个或多个元素去掉之后得到的结果。(不要求连续)
子串:给定串中任意个连续的字符组成的子序列称为该串的子串。(必须连续)

字符序列: {a,b,c,d,e,f,g,h}, 它的子序列: {a,c,e,f}
即元素b,d,g,h被去掉后,保持原有的元素序列所得到的结果就是子序列。同理,{a,h},{c,d,e}等都是它的子序列。
它的字串:{c,d,e,f} 即连续元素c,d,e,f组成的串是给定序列的字串。同理,{a,b,c,d},{g,h}等都是它的字串。

给定序列s1={1,3,4,5,6,7,7,8},s2={3,5,7,4,8,6,7,8,2},
s1和s2的相同子序列,且该子序列的长度最长,即是LCS。 s1和s2的其中一个最长公共子序列是 {3,4,6,7,8}

2.动态规划

求解LCS问题,不能使用暴力搜索方法。一个长度为n的序列拥有 2的n次方个子序列它的时间复杂度是指数阶,太恐怖了解决LCS问题,需要借助动态规划的思想。

动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。

与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。
````若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够==保存==已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。`不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。这就是动态规划法的基本思路。

3.特征分析

   解决LCS问题,需要把原问题分解成若干个子问题,所以需要刻画LCS的特征。设A=“a0,a1,…,am”,B=“b0,b1,…,bn”,且Z=“z0,z1,…,zk”为它们的最长公共子序列。不难证明有以下性质:如果am=bn,则zk=am=bn,且“z0,z1,…,z(k-1)”是“a0,a1,…,a(m-1)”和“b0,b1,…,b(n-1)”的一个最长公共子序列;如果am!=bn,则若zk!=am,蕴涵“z0,z1,…,zk”是“a0,a1,…,a(m-1)”和“b0,b1,…,bn”的一个最长公共子序列;如果am!=bn,则若zk!=bn,蕴涵“z0,z1,…,zk”是“a0,a1,…,am”和“b0,b1,…,b(n-1)”的一个最长公共子序列。有些同学,一看性质就容易晕菜,所以我给出一个图来让这些同学理解一下:


S1={1,3,4,5,6,7,7,8}
S2={3,5,7,4,8,6,7,8,2}
1---------------------------------------------------------------------------------
假如S1的最后一个元素 与 S2的最后一个元素相等,那么S1和S2的LCS就等于
{S1减去最后一个元素} 与 {S2减去最后一个元素} 的 LCS +S1和S2相等的最后一个元素。
2---------------------------------------------------------------------------------
假如S1的最后一个元素 与 S2的最后一个元素不等(本例子就是属于这种情况),那么S1和S2的LCS就等于 :
max{S1减去最后一个元素} 与 S2 的LCS, {S2减去最后一个元素} 与 S1 的LCS }。

####4.递归公式
第3节说了LCS的特征,我们可以发现,假设我需要求 a1 … am 和 b1 … b(n-1)的LCS 和 a1 … a(m-1) 和 b1 … bn的LCS,一定会]递归地并且重复地把如a1… a(m-1) 与 b1 … b(n-1) 的 LCS 计算几次。所以我们需要一个数据结构来记录中间结果,避免重复计算。

假设我们用

c[i,j]表示Xi 和 Yj 的LCS的长度

(直接保存最长公共子序列的中间结果不现实,需要先借助LCS的长度)。

X = {x1 … xm},
Y={y1…yn},
Xi = {x1 … xi},
Yj={y1… yj}。可得递归公式如下:

5.计算LCS的长度
以s1={1,3,4,5,6,7,7,8},s2={3,5,7,4,8,6,7,8,2}为例

图中的空白格子需要填上相应的数字(这个数字就是c[i,j]的定义,记录的LCS的长度值)。填的规则依据递归公式,简单来说:如果横竖(i,j)对应的两个元素相等,该格子的值

= c[i-1,j-1] + 1。如果不等,取c[i-1,j] 和 c[i,j-1]的最大值。首先初始化该表:

      然后,一行一行地从上往下填:

      S1的元素3 与 S2的元素3 相等,所以 c[2,1] = c[1,0] + 1。继续填充:

在这里插入图片描述S1的元素3 与 S2的元素5 不等,c[2,2] =max(c[1,2],c[2,1]),图中c[1,2] 和 c[2,1] 背景色为浅黄色。

        继续填充:




中间几行填写规则不变,直接跳到最后一行:
至此,该表填完。根据性质,c[8,9] = S1 和 S2 的 LCS的长度,即为5。

6.构造LCS

本文S1和S2的最LCS并不是只有1个,本文并不是着重讲输出两个序列的所有LCS,只是介绍如何通过上表,输出其中一个LCS。
我们根据递归公式构建了上表,我们将从最后一个元素c[8][9]倒推出S1和S2的LCS。

   c[8][9] = 5,且S1[8] != S2[9],所以倒推回去,c[8][9]的值来源于c[8][8]的值(因为c[8][8] > c[7][9])。c[8][8] = 5,  且S1[8] = S2[8], 所以倒推回去,c[8][8]的值来源于 c[7][7]。以此类推,如果遇到
S1[i] != S2[j] ,且c[i-1][j] = c[i][j-1]
   这种存在分支的情况,这里请都选择一个方向(之后遇到这样的情况,也选择相同的方向)

第一种结果为:

      这就是倒推回去的路径,棕色方格为相等元素,即LCS = {3,4,6,7,8},这是其中一个结果。如果如果遇到S1[i] != S2[j] ,且c[i-1][j] = c[i][j-1] 这种存在分支的情况,选择另一个方向,会得到另一个结果。


即LCS ={3,5,7,7,8}。

7.关于时间复杂度

构建c[i][j]表需要Θ(mn),输出1个LCS的序列需要Θ(m+n)。
参考
https://blog.csdn.net/hrn1216/article/details/51534607?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control

动态规划 最长公共子序列 过程图解相关推荐

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

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

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

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

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

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

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

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

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

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

  6. 算法导论之动态规划(最长公共子序列和最优二叉查找树)

    动态规划师通过组合子问题的解而解决整个问题,将问题划分成子问题,递归地求解各子问题,然后合并子问题的解而得到原问题的解.和分治算法思想一致,不同的是分治算法适合独立的子问题,而对于非独立的子问题,即各 ...

  7. 【啃不完的算法导论】- 动态规划 - 最长公共子序列(概念篇)

    以下内容纯是为了熟悉<算法导论>中的内容,高手可略过,其中涉及的书本内容的版权归原作者.译者.出版社所有 ========================================= ...

  8. 动态规划-最长公共子序列-最长递增子序列-最大递增子序列和-miking time

    1. 最长公共子序列 假设 X 和 Y 的序列如下: X[1...m] = {A, B, C, B, D, A, B} Y[1...n] = {B, D, C, A, B, A} 可以看出,X 和 Y ...

  9. 算法设计-动态规划——最长公共子序列

    算法介绍 动态规划: 动态规划算法通常用于求解具有某种最优性质的问题.在这类问题中,可能会有许多可行解.每一个解都对应于一个值,我们希望找到具有最优值的解.动态规划算法与分治法类似,其基本思想也是将待 ...

最新文章

  1. 详细透彻的分析DM9000网卡驱动程序(4)
  2. 【正一专栏】巴萨耗光了所有的激情和精力
  3. 【转:SAP学习篇】Fiori 的基本架构
  4. 【IT笔试面试题整理】判断链表是否存在环路,并找出回路起点
  5. java搜索string_java – 在数组列表中搜索最常见的String
  6. Hive Shell
  7. 转载:Mongodb start
  8. IntelliJ IDEA 编辑器配置vue高亮显示
  9. 中国电信叫停不限量套餐 套外资费3元/GB
  10. jieba结巴分词--关键词抽取_初学者 | 知否?知否?一文学会Jieba使用方法
  11. 广州某IT公司HR招开发:“不加班的都是垃圾 ”、“考不上本科是智商有问题”,网友:听了想打人...
  12. C++课程设计(电影院自助售票管理系统)
  13. 写个爬虫,爬图片,mzitu
  14. CAD怎么统计图纸中的设备材料?
  15. 【安信可IDE 1.5模板专题2】安信可windows一体化环境IDE V1.5 ESP8266 SDK二次开发直连阿里云飞燕平台,天猫精灵语音控制;
  16. 烽火路由路虚拟服务器,烽火路由器怎么设置?烽火路由器设置详解
  17. 机器学习流程及详细内容(4)
  18. 福大2021计算机考研科目,2021计算机考研专业课发生改变的院校情况汇总
  19. 【Python05】Python转义字符
  20. a55 matlab排列组合_matlab 排列组合函数的用法

热门文章

  1. 深度学习第一章(rnn)
  2. AS使用Viewbinding出现Could not find method buildFeatures() for arguments报错
  3. Django migrate 报错,通过fake 和 --fake-initial来修复
  4. 时光金科php_发布中国首个社区敬老宣言,共敬美好岁月-金科全国首届重阳敬老节温暖落幕...
  5. GDI+ 中图片的绘制
  6. 1 进 2 出 HDMI 1.4 分配器,带 HDCP 引擎、抖动清除和信号中继
  7. 神经网络相关性系数r公式,神经网络预测数据
  8. 知道创宇云安全发布服务器安全产品-365门神
  9. win10蓝屏代码_电脑蓝屏代码在哪看?如何解决
  10. java 数字转大写 100行内搞定