最长公共子序列
一、最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(LongestCommon Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。
例如:X(A,B,C,B,D,A,B)
Y(B,D,C,A,B,A)
那么最长公共子序列就是:B,C,B,A
二、算法设计:
方法一、穷举法
解最长公共子序列问题时最容易想到的算法是穷举搜索法,即对X的每一个子序列,检查它是否也是Y的子序列,从而确定它是否为X和Y的公共子序列,并且在检查过程中选出最长的公共子序列。X和Y的所有子序列都检查过后即可求出X和Y的最长公共子序列。X的一个子序列相应于下标序列{1, 2, …, m}的一个子序列,因此,X共有2m个不同子序列(Y亦如此,如为2^n),从而穷举搜索法需要指数时间(2^m * 2^n)。
方法二、用动态规划方法解决
最长公共子序列的结构:
设X = { x1 ,... , xm },Y = { y1 , ... , yn }及它们的最长子序列Z= { z1 , ... , zk }则:
1、若 xm = yn , 则 zk = xm = yn,且Z[k-1] 是 X[m-1] 和 Y[n-1] 的最长公共子序列
2、若 xm != yn ,且 zk != xm, 则 Z 是 X[m-1] 和 Y 的最长公共子序列
3、若 xm != yn , 且 zk != yn, 则 Z 是 Y[n-1] 和 X 的最长公共子序列
子问题的递归结构:
1、当 i = 0 , j = 0 时 , c[i][j] = 0
2、当 i , j > 0 ; x[i-1] = y[j-1] 时 , c[i][j] = c[i-1][j-1] + 1
3、当 i , j > 0 ; xi[i-1]!= y[j-1] 时 , c[i][j] = max { c[i][j-1] , c[i-1][j] }
算法:
打印(回溯法):
由于每次调用至少向上或向左(或向上向左同时)移动一步,故最多调用(m + n)次就会遇到i = 0或j = 0的情况,此时开始返回。返回时与递归调用时方向相反,步数相同,故算法时间复杂度为Θ(m + n)。