最长公共子序列(LCS)是衡量两个序列的相似度的一种方式,其形式化定义可见《Introduction to Algorithms》Page 209。
注意到子序列和子串的区别,子序列中的元素在原序列中可以使不连续的,亦即,对于任意序列(x1,x2,x3......xm),可选择每一个元素是否在其子序列中,从而共有2的m次方个子序列,因为对于任一元素xi(0<i<m+1),要么在其子序列中,要么不在。
对给出的两个序列,(x1,x2,x3......xm),(y1,y2,y3......yn),求两者LCS。
1、 显然的算法:
对序列(x1,x2,x3......xm)的任意子序列,检验他是否为(y1,y2,y3......yn)的子序列,然后取最长即为所求。
时间分析:
有前面可知,求(x1,x2,x3......xm)的所有子序列的时间复杂度是O(2m),检测每一个子序列是否为(y1,y2,y3......yn)的子序列的时间复杂度是O(N),所以总的时间复杂度是 O(N2m),显然这个代价太大了。
2、动态规划算法:
上一篇文章中提到,动态规划解题的关键在于找到最优子结构和重叠子问题。
LCS问题的最优子结构:
对于Xm=(x1,x2,x3......xm)和Yn=(y1,y2,y3......yn),从后向前扫描,如果最后的元素xm=yn,那么zk=xm=yn肯定在最有子序列中,问题转化为求(x1,x2,x3......xm-1)和
(y1,y2,y3......yn-1)的LCS。
当然如果Xm=Yn,则上面的条件一直成立,LCS即为(x1,x2,x3......xm)或(y1,y2,y3......yn),问题的关键在于xm!=yn怎么办。
如果xm!=yn,那么Xm和Yn的LCS,要么等于X(m-1)和Yn的LCS,要么等于Xm和Yn-1的LCS,确切的说,是等于两者之中较长的一个。
如果令C[i,j]表示Xi和Yj的LCS的长度,那么该问题的最优子结构可以描述为:
·
重叠子问题是显然的:c[i-1,j]和c[i,j-1],都包含c[i-1,j-1]的求解过程,而c[i-1,j]和c[i,j-1]的结果,都可能用在c[i,j+1],c[i+1,j]的求解中,这个问题中的重叠子问题是比较多 的。
到这里,写出一个给予表结构的,自底向上的的动态规划已经水到渠成了。