[算法] 最长公共子序列

问题

  • 一个序列 S S 任意删除若干个字符得到新序列 T T ,则 T T 叫做 S S 的子序列;
  • 两个序列 X X Y Y 的公共子序列中,长度最长的那个,定义为 X X Y Y 的最长公共子序列(LCS,Longest Common Subsequence):
    • 字符串 13455 13455 245576 245576 的最长公共子序列为 455 455
    • 字符串 acdfg a c d f g adfc a d f c 的最长公共子序列为 adf a d f
  • 注意区别最长公共子串(Longest Common Substring)
    • 最长公共子串要求连续

分析

暴力求解法

  • 假定字符串 X X Y Y 的长度分别为 m m n n ;
  • X X 的一个子序列即下标序列 {12...m} { 1 , 2 , . . . , m } 的严格递增子序列,因此 X X 共有 2m 2 m 个不同的子序列;同理, Y Y 2n 2 n 个不同子序列,从而穷举搜索法需要指数时间 O(2m2n) O ( 2 m ∗ 2 n )
  • X X 的每一个子序列,检查它是否也是 Y Y 的子序列,从而确定它是否为 X X Y Y 的公共子序列,并且在检查过程中选出最长的公共子序列;

LCS解法探索

LCS的记号

  • 字符串 X X ,长度为 m m ,从1开始数;
  • 字符串 Y Y ,长度为 n n ,从1开始数;
  • Xi=<x1,...,xi> X i =< x 1 , . . . , x i > X X 序列的前 i i 个字符( 1im 1 ≤ i ≤ m )( Xi X i 不妨读作字符串 X X i i 前缀);
  • Yj=<y1,...,yi> Y j =< y 1 , . . . , y i > Y Y 序列的前 j j 个字符( 1jn 1 ≤ j ≤ n )(字符串 Y Y j j 前缀);
  • LCS(X,Y) L C S ( X , Y ) 为字符串 X X Y Y 的最长公共子序列,即为 Z=<z1,...,zk> Z =< z 1 , . . . , z k >
    • 注意:事实上, X X Y Y 可能存在多个子串,长度相同并且最大,因此, LCS(X,Y) L C S ( X , Y ) 严格的说,是个字符串集合。即 ZLCS(X,Y) Z ∈ L C S ( X , Y )

若 xm=yn

你可能感兴趣的:(算法,C/C++)