几个月前已经弄懂了的算法,现在回忆起来这么费劲。又得重头开始,真是浪费生命啊。再好的脑袋也不如烂笔头!
这里用最长公共子序列问题(LCS)来说明算法: 给定两个序列
X = <X1,X2, ... ,Xm>
Y = <Y1,Y2, ... ,Ym>
求X、Y长度最长的公共子序列。
前期储备知识:公共子序列不等于公共字串(注意区分)。例如,如果X = <A,B,C,B,D,A,B>,Y = <B,D,C,A,B,A>,那么<B,C,A>就是X和Y的公共子序列,但不是最长公共子序列,<B,C,B,A>才是最长公共子序列,当然<B,D,A,B>也是最长公共子序列。
定理:令X = X1,X2,... ,Xm 和 Y = Y1,Y2, ..., Yn为两个序列,Z= Z1,Z2,..., Z为X和Y的任意LCS。
1、如果Xm = Yn,则Zk = Xm = Yn且Zk-1是Xm-1和Yn-1的一个LCS。
2、如果Xm != Yn,那么Zk != Xm意味着Z是Xm-1和Y的一个LCS。
3、如果Xm != Yn,那么Zk != Ym意味着Z是X和Yn-1的一个LCS。
( 用反证法即可证明。对证明有疑问的可以去看算法导论。)
定义c[i,j]表示Xi和Yj的LCS长度。如果i=0或j=0,即一个序列长度为0,那么LCS的长度为0。根据子结构的性质,则有如下表达式:
c[i,j] = 0 若i=0或j=0
= c[i-1,j-1] + 1 若i,j>0 且 Xi = Yi
= max(c[i,j-1],c[i-1,j]) 若i,j>0且Xi != Yi
OK,最关键的一步推导出了,根据该公式很容易推导出下面的图(数字表示子序列的长度):
定义数组b[m,n]来存储子序列的长度,显然b[0,0~n] = 0,b[0~m,0] = 0。