最大公共子序列
给定序列
X = < X1,X2,…,Xm >
Y = < Y1,Y2,…,Yj >
求X和Y的最长公共子序列。
算法思想
- 动态规划法
Xi = < x1,x2,…,xi >
Yj = < y1,y2,…,yj >
Zk = < z1,z2,…,zk >
如果Zk是Xi和Yj的最长公共子序列
(1)xi = yj,那么 zk = xi = yj,Zk-1 是 Xi-1 和Yj-1的最长公共子序列
(2)xi ≠ yj,zk ≠ xi,那么 Zk是Xi-1和 Yj 的最长公共子序列
(3)xi ≠ yj,zk ≠ yj,那么 Zk 是 Xi 和 Yj-1 的最长公共子序列
进而得出递推关系
实例:
X=<A,B,D,C,B,A,C>
Y=<B,C,A,D,A,A>
m=0-7
n=0-6
初始化
i/j | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | ||||||
2 | 0 | ||||||
3 | 0 | ||||||
4 | 0 | ||||||
5 | 0 | ||||||
6 | 0 | ||||||
7 | 0 |
算法1:
(1)i=1
- j=1,X.A<>Y.B:C[1,1]=max(C[0,1],C[1,0])=max(0,0)=0,删除x
- j=2,X.A<>Y.C:C[1,2]=max(C[0,2],C[1,1])=max(0,0)=0,删除x
- j=3,X.A==Y.A:C[1,3]=C[0,2]+1=0+1=1,删除两个
- j=4,X.A<>Y.D:C[1,4]=max(C[0,4],C[1,3])=max(0,1)=1,删除y
- j=5,X.A==Y.A:C[1,5]=C[0,4]+1=0+1=1,删除两个
- j=6,X.A==Y.A:C[1,6]=C[0,5]+1=0+1=1,删除两个
(2)i=2
- j=1,X.B= =Y.B:X2==Y1,C[2,1]=C[1,0]+1=0+1=1,删除两个
- j=2,X.B<>Y.C:X2<>Y2,C[2,2]=max(C[1,2],C[2,1])=max(0,1)=1,删除y
- j=3,X.B<>Y.A:X2<>Y3,C[2,3]=max(C[1,3],C[2,2])=max(1,1)=1,删除x
- j=4,X.B<>Y.D:X2<>Y4,C[2,4]=max(C[1,4],C[2,3])=max(1,1)=1,删除x
- j=5,X.B<>Y.A:X2<>Y5,C[2,5]=max(C[1,5],C[2,4])=max(1,1)=1,删除x
- j=6,X.B<>Y.A:X2<>Y6,C[2,6]=max(C[1,6],C[2,5])=max(1,1)=1,删除x
(3)i=3
- j=1,X.D<>Y.B:X3<>Y1,C[3,1]=max(C[2,1],C[3,0])=max(1,0)=1,删除x
- j=2,X.D<>Y.C:X3<>Y2,C[3,2]=max(C[2,2],C[3,1])=max(1,1)=1,删除x
- j=3,X.D<>Y.A:X3<>Y3,C[3,3]=max(C[2.3],C[3,2])=max(1,1)=1,删除x
- j=4,X.D= =Y.D:X3==Y4,C[3,4]=C[2,3]+1=2,删除两个
- j=5,X.D<>Y.A:X3<>Y5,C[3,5]=max(C[2,5],C[3,4])=max(1,2)=2,删除y
- j=6,X.D<>Y.A:X3<>Y6,C[3,6]=max(C[2,6],C[3,5])=max(1,2)=2,删除y
(4)i=4
- j=1,X.C<>Y.B:X4<>Y1,C[4,1]=max(C[3,1],C[4,0])=max(1,0)=1,删除x
- j=2,X.C= =Y.C:X4==Y2,C[4,2]=C[3,1]+1=2,删除两个
- j=3,X.C<>Y.A:X4<>Y3,C[4,3]=max(C[3,3],C[4,2])=max(1,2)=2,删除y
- j=4,X.C<>Y.D:X4<>Y4,C[4,4]=max(C[3,4],C[4,3])=max(2,2)=2,删除x
- j=5,X.C<>Y.A:X4<>Y5,C[4,5]=max(C[3,5],C[4,4])=max(2,2)=2,删除x
- j=6,X.C<>Y.A:X4<>Y6,C[4,6]=max(C[3,6],C[4,5])=max(2,2)=2,删除x
(5)i=5
- j=1,X.B= =Y.B:X5==Y1,C[5,1]=C[4,0]+1=0+1=1,删除两个
- j=2,X.B<>Y.C:X5<>Y2,C[5,2]=max(C[4,2],C[5,1])=max(2,1)=2,删除x
- j=3,X.B<>Y.A:X5<>Y3,C[5,3]=max(C[4,3],C[5,2])=max(2,2)=2,删除x
- j=4,X.B<>Y.D:X5<>Y4,C[5,4]=max(C[4,4],C[5,3])=max(2,2)=2,删除x
- j=5,X.B<>Y.A:X5<>Y5,C[5,5]=max(C[4,5],C[5,4])=max(2,2)=2,删除x
- j=6,X.B<>Y.B:X5<>Y6,C[5,6]=max(C[4,6],C[5,5])=max(2,2)=2,删除x
(6)i=6
- j=1,X.A<>Y.B:X6<>Y1,C[6,1]=max(C[5,1],C[6,0])=max(1,0)=1,删除x
- j=2,X.A<>Y.C:X6<>Y2,C[6,2]=max(C[5,2],C[6,1])=max(2,1)=2,删除x
- j=3,X.A==Y.A:X6=Y3,C[6,3]=C[5,2]+1=2+1=3,删除两个
- j=4,X.A<>Y.D:X6<>Y4,C[6,4]=max(C[5,4],C[6,3])=max(2,3)=3,删除y
- j=5,X.A= =Y.A:X6==Y5,C[6,5]=C[5,4]+1=2+1=3,删除两个
- j=6,X.A= =Y.A:X6==Y6,C[6,6]=C[5,5]+1=2+1=3,删除两个
(7)i=7
- j=1,X.C<>Y.B:X7<>Y1,C[7,1]=max(C[6,1],C[7,0])=max(1,0)=1,删除x
- j=2,X.C==Y.C:X7<>Y2,C[7,2]=C[6,1]+1=1+1=2,删除两个
- j=3,X.C<>Y.A:X7<>Y3,C[7,3]=max(C[6,3],C[7,2])=max(3,2)=3,删除x
- j=4,X.C<>Y.D:X7<>Y4,C[7,4]=max(C[6,4],C[7,3])=max(3,3)=3,删除x
- j=5,X.C<>Y.A:X7<>Y5,C[7,5]=max(C[6,5],C[7,4])=max(3,3)=3,删除x
- j=6,X.C<>Y.A:X7<>Y6,C[7,6]=max(C[6,6],C[7,5])=max(3,3)=3,删除x
B[i][j]
i/j | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0;删除x | 0;删除x | 1;删除两个 | 1;删除y | 1;删除两个 | 1;删除两个 |
2 | 0 | 1;删除两个 | 1;删除y | 1;删除x | 1;删除x | 1;删除x | 1;删除x |
3 | 0 | 1;删除x | 1;删除x | 1;删除x | 2;删除两个 | 2;删除y | 2;删除y |
4 | 0 | 1;删除x | 2;删除两个 | 1;删除y | 1;删除x | 1;删除x | 1;删除x |
5 | 0 | 1;删除两个 | 2;删除x | 2;删除x | 2;删除x | 2;删除x | 2;删除x |
6 | 0 | 1;删除x | 2;删除x | 3;删除两个 | 3;删除y | 1;删除两个 | 3;删除两个 |
7 | 0 | 1;删除x | 2;删除两个 | 3;删除x | 3;删除x | 3;删除x | 3;删除x |
算法2:
(1) X=7,Y=6
查表 (7,6) “3;删除x”
X=<A,B,D,C,D,A,C>
Y=<B,C,A,D,A,A>
=>
X=<A,B,D,C,D,A>
Y=<B,C,A,D,A,A>
(2) X=6,Y=6
查表 (6,6) “3;删除两个”
X=<A,B,D,C,D,A>
Y=<B,C,A,D,A,A>
=>
X=<A,B,D,C,D>
Y=<B,C,A,D,A>
输出A
(3)X=5,Y=5
查表 (5,5) “2;删除x”
X=<A,B,D,C,D>
Y=<B,C,A,D,A>
=>
X=<A,B,D,C>
Y=<B,C,A,D,A>
(4)X=4,Y=5
查表 (4,5) “2;删除x”
X=<A,B,D,C,>
Y=<B,C,A,D,A>
=>
X=<A,B,D>
Y=<B,C,A,D,A>
(5)X=3,Y=5
查表 (3,5) “2;删除y”
X=<A,B,D>
Y=<B,C,A,D,A>
=>
X=<A,B,D >
Y=<B,C,A,D>
(6)X=3,Y=4
查表 (3,4) “2;删除两个”
X=<A,B,D>
Y=<B,C,A,D>
=>
X=<A,B>
Y=<B,C,A>
输出D
(7)X=2,Y=3
查表 (2,3) “1;删除x”
X=<A,B>
Y=<B,C,A>
=>
X=<A,>
Y=<B,C,A>
(8)X=1,Y=3
查表 (1,3) “1;删除两个”
X=<A,>
Y=<B,C,A>
=>
X=<>
Y=<B,C>
输出A
(9)X=0,Y=2
算法结束,输出 <A,D,A>
核心伪代码
- 算法1 给出最长子串长度
int LCS() {
C[0,j] = C[i,0] = 0,1≤i≤m,i≤j≤n
for (i=1 to m) {
for (j=1 to n) {
if (X[i] == Y[j]) {
C[i][j] = C[i - 1][j - 1] + 1;
B[i][j] = 'D';
}
else if (C[i - 1][j] > C[i][j - 1]) {
C[i][j] = C[i - 1][j];
B[i][j] = 'X';
}
else {
C[i][j] = C[i][j - 1];
B[i][j] = 'Y';
}
}
}
return C[n - 1][m - 1];
}
- 算法2 输出最长子串
void f(B, i, j) {
if (i < 0 || j < 0)
return;
if (B[i][j] = “删除两个”) {
Stack.push(X[i]);//存入栈内
f(B, i - 1, j - 1);
}
else if (B[i][j] == “删除X”)
f(B, i - 1, j);
else
f(B, i, j - 1);
}
算法复杂度分析
最后算法复杂度即算法1为O(mn)