一、基本概念

LCS是最长公共子序列(Longest common subsequence problem)的缩写。LCS问题是在一组序列(通常只有两个序列)中找到所有序列共有的最长子序列的问题。它与最长公共子串问题不同:与子串不同,子序列不需要占据原始序列中的连续位置。最长公共子序列问题是经典的计算机科学问题,是 diff 实用程序等数据比较程序的基础,在计算语言学和生物信息学中有应用。它还被 Git 等版本控制系统广泛用于协调对受版本控制的文件集合所做的多项更改。

例如,考虑序列 (ABCD) 和 (ACBAD)。它们有 5 个长度为 2 的公共子序列:(AB)、(AC)、(AD)、(BD) 和 (CD); 2个长度为3的公共子序列:(ABD)和(ACD);并且不再有更长的公共子序列。所以 (ABD) 和 (ACD) 是它们最长的公共子序列。

  • 复杂度:

对于任意数量的输入序列的一般情况,问题是 NP-hard。[1]当序列数不变时,该问题可通过动态规划在多项式时间内求解。

二、两个序列的解决方案

LCS 问题有一个最优子结构:问题可以分解为更小、更简单的子问题,而这些子问题又可以分解为更简单的子问题,依此类推,直到最终解决方案变得微不足道。 LCS 尤其具有重叠的子问题:高级子问题的解决方案通常重用低级子问题的解决方案。具有这两个属性的问题适用于动态规划方法,其中子问题解决方案被记忆,即子问题的解决方案被保存以供重用。

S的前缀定义为S的前n个字符[5]例如,S = (AGCA) 的前缀是

假设 LCS(X, Y) 是一个计算 X 和 Y 共有的最长子序列的函数。这样的函数有两个有趣的属性。

2.1 第一个属性

  • 两个字符串具有相同尾序,那么同时去掉两者的尾序,不影响它们的距离

LCS(X^A,Y^A) = LCS(X,Y)^A,对于所有字符串 X、Y 和所有符号 A,其中 ^ 表示字符串连接。这允许简化以相同符号结尾的两个序列的 LCS 计算。例如,LCS("BANANA","ATANA") = LCS("BANAN","ATAN")^"A",继续其余常用符号,LCS("BANANA","ATANA") = LCS("BAN","AT")^"ANA"。

2.2 第二个属性

  • 如果 A 和 B 是不同的符号 (A≠B),则 LCS(X^A,Y^B) 是以下两者的最大者:LCS(X^A,Y), LCS(X,Y ^B) },适用于所有字符串 X、Y。

例如,LCS("ABCDEFG","BCDGK") 是 LCS("ABCDEFG","BCDG") 和 LCS("ABCDEF","BCDGK") 中最长的字符串;如果两者碰巧长度相等,则可以任意选择其中之一。

        证明,分两种情况:

  • 如果 结尾,那么最后的不能在 LCS 中,因此
  • 如果 不以 结尾,则最后的 不能在 LCS 中,因此

2.3 LCS 函数的定义

让两个序列定义如下: 的前缀是; 的前缀是。令 表示最长的集合前缀  的公共子序列。这组序列由以下给出。

要找到   和 ,请比较。如果它们相等,则序列
扩展成​。如果它们不相等,则下面两个序列中最长的被保留, 。 (如果它们的长度相同,则保留两者。)

三、两个序列的应用实例

示例:找到 R = (GAC) 和 C = (AGCAT) 共有的最长子序列。因为 LCS 函数使用“第零”元素,所以为这些序列定义空的零前缀很方便:R0 = Ø;和 C0 = Ø。所有前缀都放在一个表中,第一行是 C(使其成为列标题),第一列是 R(使其成为行标题)。

该表用于存储每个计算步骤的 LCS 序列。第二列和第二行已经用Ø填充了,因为当一个空序列与一个非空序列进行比较时,最长的公共子序列总是一个空序列。

LCS(R1, C1) 通过比较每个序列中的第一个元素来确定。 G 和 A 不相同,所以这个 LCS 获得(使用“第二个属性”)两个序列中最长的一个,LCS(R1, C0) 和 LCS(R0, C1)。根据表格,这两个都是空的,所以 LCS(R1, C1) 也是空的,如下表所示。箭头表示序列来自上方的单元格 LCS(R0, C1) 和左侧的单元格 LCS(R1, C0)。

LCS(R1,C2)是通过比较G和G来确定的。它们匹配,所以将G附加到左上序列,LCS(R0,C1),即(Ø),给出(ØG),即(G) .

对于 LCS(R1, C3),G 和 C 不匹配。上面的序列是空的;左边的一个包含一个元素,G。选择其中最长的一个,LCS(R1,C3)是(G)。箭头指向左侧,因为这是两个序列中最长的。

LCS(R1, C4), likewise, is (G).

LCS(R1, C5), likewise, is (G).

对于 LCS(R2, C1),将 A 与 A 进行比较。两个元素匹配,因此将 A 附加到 Ø,得到 (A)。

对于LCS(R2,C2),A和G不匹配,所以使用LCS(R1,C2)中最长的(G)和LCS(R2,C1)中最长的(A)。在这种情况下,它们每个都包含一个元素,因此这个 LCS 有两个子序列:(A) 和 (G)。

对于 LCS(R2, C3),A 与 C 不匹配。 LCS(R2, C2) 包含序列 (A) 和 (G); LCS(R1, C3) 是 (G),它已经包含在 LCS(R2, C2) 中。结果是 LCS(R2, C3) 还包含两个子序列 (A) 和 (G)。

对于 LCS(R2, C4),A 匹配附加到左上角单元格的 A,给出 (GA)。

对于LCS(R2,C5),A不匹配T。比较(GA)和(G)这两个序列,最长的是(GA),所以LCS(R2,C5)就是(GA)。

对于 LCS(R3, C1),C 和 A 不匹配,因此 LCS(R3, C1) 获得两个序列中最长的 (A)。

对于 LCS(R3, C2),C 和 G 不匹配。 LCS(R3, C1) 和 LCS(R2, C2) 都有一个元素。结果是 LCS(R3, C2) 包含两个子序列,(A) 和 (G)。

对于 LCS(R3, C3),C 和 C 匹配,因此 C 被附加到 LCS(R2, C2) 中,其中包含 (A) 和 (G) 两个子序列,得到 (AC) 和 (GC)。

对于 LCS(R3, C4),C 和 A 不匹配。将包含 (AC) 和 (GC) 的 LCS(R3, C3) 和包含 (GA) 的 LCS(R2, C4) 组合起来,总共得到三个序列:(AC)、(GC) 和 (GA) )。

最后,对于 LCS(R3, C5),C 和 T 不匹配。结果是 LCS(R3, C5) 还包含三个序列,(AC)、(GC) 和 (GA)。

最终的结果是最后一个单元格包含了(AGCAT)和(GAC)共有的所有最长子序列;它们是 (AC)、(GC) 和 (GA)。该表还显示了每对可能的前缀的最长公共子序列。例如,对于 (AGC) 和 (GA),最长的公共子序列是 (A) 和 (G)。

四、追溯方法

计算LCS表中一行的LCS只需要当前行和上一行的解。尽管如此,对于长序列,这些序列可能会变得很多而且很长,需要大量的存储空间。存储空间可以通过保存的不是实际的子序列,而是子序列的长度和箭头的方向来节省,如下表所示。

实际的子序列在“追溯”过程中推导出来,该过程从表中的最后一个单元格开始,沿着箭头向后。当长度减小时,这些序列必须有一个共同的元素。当一个单元格中显示两个箭头时,可能有多个路径。下表是此类分析的表格,其中长度即将减少的单元格中带有颜色的数字。粗体数字描绘了序列,(GA)。

编辑距离:最长公共子序列-LCS问题相关推荐

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

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

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

    最长公共子序列(LCS,Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最 ...

  3. 程序员编程艺术第十一章:最长公共子序列(LCS)问题

    程序员编程艺术第十一章:最长公共子序列(LCS)问题 0.前言 程序员编程艺术系列重新开始创作了(前十章,请参考程序员编程艺术第一~十章集锦与总结).回顾之前的前十章,有些代码是值得商榷的,因当时的代 ...

  4. 算法之最长公共子序列(LCS)问题

    算法课上老师留的作业,最长公共子序列LCS(Longest Common Subsequence)问题,首先看到这个问题感觉有点复杂,和最长公共子串不同,公共子序列并不要求元素相邻,看起来只有穷举才能 ...

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

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

  6. python实现求解最长公共子序列LCS问题

    在实现论文<Automatically Generating Models for Botnet Detection>论文的算法中,用到了一个The longest commom subs ...

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

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

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

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

  9. 最长公共子序列 (LCS) 详解+例题模板(全)

    欢迎访问https://blog.csdn.net/lxt_Lucia-- 宇宙第一小仙女\(^o^)/-萌量爆表求带飞=≡Σ((( つ^o^)つ~ dalao们点个关注呗- ------------ ...

  10. 相似度:最长公共子序列--LCS

    一.概念 1.子序列 一个特定序列的子序列就是将给定序列中零个或多个元素去掉后得到的结果(不改变元素间相对次序).如序列[A,B,C,B,D,A,B]的子序列有:[A,B],[B,C,A],[A,D, ...

最新文章

  1. linux 瞬间文件数没了,关于linux:如何快速汇总文件中的所有数字?
  2. 微软亚研院副院长周明:从语言智能到代码智能
  3. ASP.NET MVC2 Web项目中公用类库的问题
  4. Ucenter社区服务搭建
  5. Hibernate中常见的异常
  6. SQL Server 2016 RC0 安装(超多图)
  7. 狂赌智能手机 中国互联网巨头深陷零利润困局
  8. 给指定Python版本安装指定版本库的办法
  9. JS小技巧 ----- 将类数组 / 字符串转为数组的几种方式
  10. 用navixt连接mysql连接不上_技嘉的RX 5500 XT、1650/1660 SUPER显卡现身欧亚经委会数据库:实锤两家中端新卡...
  11. ORACLE VARCHAR2
  12. WIN10下搭建vue开发环境
  13. afudos备份bios不动_afudos备份bios不动_老鸟经验之谈刷坏BIOS后的2种恢复方法
  14. 微信小程序开发详解(九)---微信小程序布局基础
  15. Ramda 函数库参考教程
  16. Linux系统carplay模块,CarPlay for Android: R12d 插件源码移植到Linux
  17. matlab费曼编码输入,多点格林函数数值积分(费曼参数积分)的程序分析及应用
  18. 今天是第几天python_今_今是什么意思_今字怎么读_今的含义_今字组词-新东方在线字典...
  19. Python进阶——循环对象
  20. 学习LSM(Linux security module)之二:编写并运行一个简单的demo

热门文章

  1. 数据可视化应用案例:从面积到人口,再到经济、房贷等等方面透析重庆市
  2. FastText情感分析和词向量训练实战——Keras算法练习
  3. tf.where() 详解
  4. Python入门100题 | 第030题
  5. 【Python刷题】_1
  6. R语言-RStudio打开中文注释的脚本后出现乱码
  7. 【LeetCode从零单排】No38.CountAndSay
  8. Java 8 Stream API详解--转
  9. java RSA加密解密--转载
  10. nginx 学习笔记(1) nginx安装