问题
最长公共子序列LCS算法
设X和Z是两个序列,其中X=<x1, x2, …,xm>,Z=< z1, z2,…, zk>
如果存在X的元素构成的按下标严格递增序列< xi1, xi2, …,xik>,使xij=zj,j=1,2,…,k,那么Z是X的子序列,Z含有的元素个数,称为子序列长度。
设定义X和Y是两个序列,如果Z既是X的子序列,也是Y的子序列,则称Z是X和Y的公共子序列。
例如:
X=<A,B,C,B,D,A,B>
Y=<B,D,C,A,B,A>
最长公共子序列为:
<B,C,A,B>
<B,C,B,A>
<B,D,A,B>
对于给定序列X=<x1, x2, …,xm>,Y=< y1, y 2,…, y j>,求X和Y的最长公共子序列。
解析
Xi=<x1, x2, …,xi>
Yj=< y1, y 2,…, y j>
Zk=< z1, z 2,…, z k>
如果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的最长公共子序列。
递推关系:
C[i,j]表示是Xi和Yj的最长公共子序列的长度
i是X长度,j是Y的长度,C[i,j]是Z的长度
实例:
X=<A,B,D,C,B,A,C>
Y=<B,C,A,D,A,A>
m=0-7
n=0-6
第一步
初始化C[i,j]
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、i=1
(1)、j=1,A≠B,X1≠Y1,C[1,1]=max{C[0,1],C[1,0]}=max{0,0}=0,删除x
(2)、j=2,A≠C,X1≠Y2,C[1,2]=max{C[0,2],C[1,1]}=max{0,0}=0,删除x
(3)、j=3,A=A,X1=Y3,C[1,3]=C[0,2]+1=0+1=1,删除x和y
(4)、j=4,A≠D,X1≠Y4,C[1,4]=max{C[0,4],C[1,3]}=max{0,1}=1,删除y
(5)、j=5,A=A,X1=Y5,C[1,5]=C[0,4]+1=0+1=1,删除x和y
(6)、j=6,A=A,X1=Y6,C[1,6]=C[0,5]+1=0+1=1,删除x和y
2、i=2
(1)、j=1,B=B,X2=Y1,C[2,1]=C[1,0]+1=0+1=1,删除x和y
(2)、j=2,B≠C,X2≠Y2,C[2,2]=max{C[1,2],C[2,1]}=max{0,1}=1,删除y
(3)、j=3,B≠A,X2≠Y3,C[2,3]=max{C[1,3],C[2,2]}=max{1,1}=1,删除x
(4)、j=4,B≠D,X2≠Y4,C[2,4]=max{C[1,4],C[2,3]}=max{1,1}=1,删除y
(5)、j=5,B≠A,X2≠Y5,C[2,5]=max{C[1,5],C[2,4]}=max{1,1}=1,删除x
(6)、j=6,B≠A,X2≠Y6,C[2,6]=max{C[1,6],C[2,5]}=max{1,1}=1,删除x
3、i=3
(1)、j=1,D≠B,X3≠Y1,C[3,1]=max{C[2,1],C[3,0]}=max{1,0}=1,删除x
(2)、j=2,D≠C,X3≠Y2,C[3,2]=max{C[2,2],C[3,1]}=max{1,1}=1,删除x
(3)、j=3,D≠A,X3≠Y3,C[3,3]=max{C[2.3],C[3,2]}=max{1,1}=1,删除x
(4)、j=4,D=D,X3=Y4,C[3,4]=C[2,3]+1=2,删除x和y
(5)、j=5,D≠A,X3≠Y5,C[3,5]=max{C[2,5],C[3,4]}=max{1,2}=2,删除y
(6)、j=6,D≠A,X3≠Y6,C[3,6]=max{C[2,6],C[3,5]}=max{1,2}=2,删除y
4、i=4
(1)、j=1,C≠B,X4≠Y1,C[4,1]=max{C[3,1],C[4,0]}=max{1,0}=1,删除x
(2)、j=2,C=C,X4=Y2,C[4,2]=C[3,1]+1=2,删除x和y
(3)、j=3,C≠A,X4≠Y3,C[4,3]=max{C[3,3],C[4,2]}=max{1,2}=2,删除y
(4)、j=4,C≠D,X4≠Y4,C[4,4]=max{C[3,4],C[4,3]}=max{2,2}=2,删除x
(5)、j=5,C≠A,X4≠Y5,C[4,5]=max{C[3,5],C[4,4]}=max{2,2}=2,删除x
(6)、j=6,C≠A,X4≠Y6,C[4,6]=max{C[3,6],C[4,5]}=max{2,2}=2,删除x
5、i=5
(1)、j=1,B=B,X5=Y1,C[5,1]=C[4,0]+1=0+1=1,删除x和y
(2)、j=2,B≠C,X5≠Y2,C[5,2]=max{C[4,2],C[5,1]}=max{2,1}=2,删除x
(3)、j=3,B≠A,X5≠Y3,C[5,3]=max{C[4,3],C[5,2]}=max{2,2}=2,删除x
(4)、j=4,B≠D,X5≠Y4,C[5,4]=max{C[4,4],C[5,3]}=max{2,2}=2,删除x
(5)、j=5,B≠A,X5≠Y5,C[5,5]=max{C[4,5],C[5,4]}=max{2,2}=2,删除x
(6)、j=6,B≠B,X5≠Y6,C[5,6]=max{C[4,6],C[5,5]}=max{2,2}=2,删除x
6、i=6
(1)、j=1,A≠B,X6≠Y1,C[6,1]=max{C[5,1],C[6,0]}=max{1,0}=1,删除x
(2)、j=2,A≠C,X6≠Y2,C[6,2]=max{C[5,2],C[6,1]}=max{2,1}=2,删除x
(3)、j=3,A=A,X6=Y3,C[6,3]=C[5,2]+1=2+1=3,删除x和y
(4)、j=4,A≠D,X6≠Y4,C[6,4]=max{C[5,4],C[6,3]}=max{2,3}=3,删除y
(5)、j=5,A=A,X6=Y5,C[6,5]=C[5,4]+1=2+1=3,删除x和y
(6)、j=6,A=A,X6=Y6,C[6,6]=C[5,5]+1=2+1=3,删除x和y
7、i=7
(1)、j=1,C≠B,X7≠Y1,C[7,1]=max{C[6,1],C[7,0]}=max{1,0}=1,删除x
(2)、j=2,C=C,X7≠Y2,C[7,2]=C[6,1]+1=1+1=2,删除x和y
(3)、j=3,C≠A,X7≠Y3,C[7,3]=max{C[6,3],C[7,2]}=max{3,2}=3,删除x
(4)、j=4,C≠D,X7≠Y4,C[7,4]=max{C[6,4],C[7,3]}=max{3,3}=3,删除x
(5)、j=5,C≠A,X7≠Y5,C[7,5]=max{C[6,5],C[7,4]}=max{3,3}=3,删除x
(6)、j=6,C≠A,X7≠Y6,C[7,6]=max{C[6,6],C[7,5]}=max{3,3}=3,删除x
最终得到C[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;删除x和y | 1;删除y | 1;删除x和y | 1;删除x和y |
2 | 0 | 1;删除x和y | 1;删除y | 1;删除x | 1;删除y | 1;删除x | 1;删除x |
3 | 0 | 1;删除x | 1;删除x | 1;删除x | 2;删除x和y | 2;删除y | 2;删除y |
4 | 0 | 1;删除x | 2;删除x和y | 2;删除y | 2;删除x | 2;删除x | 2;删除x |
5 | 0 | 1;删除x | 2;删除x | 2;删除x | 2;删除x | 2;删除x | 2;删除x |
6 | 0 | 1;删除x | 2;删除x | 3;删除x和y | 3;删除y | 3;删除x和y | 3;删除x和y |
7 | 0 | 1;删除x | 2;删除x和y | 3;删除x | 3;删除x | 3;删除x | 3;删除x |
第二步
(1)、X=7,Y=6
查表C(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
查表C(6,6)得“3;删除x和y”
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
查表C(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
查表C(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
查表C(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
查表C(3,4)得“2;删除x和y”
X=<A,B,D>
Y=<B,C,A,D>
=>
X=<A,B>
Y=<B,C,A>
输出D
(7)、X=2,Y=3
查表C(2,3)得“1;删除x”
X=<A,B>
Y=<B,C,A>
=>
X=<A,>
Y=<B,C,A>
(8)、X=1,Y=3
查表C(1,3)得“1;删除x和y”
X=<A,>
Y=<B,C,A>
=>
X=<>
Y=<B,C>
输出A
(9)、X=0,Y=2
算法结束,输出<A,D,A>
核心代码
//找到最长公共子串的长度
public static void findMaxLength() {
//初始化C[i,j]
for (int i = 0; i < X.length; i++) {
C[i][0]=0;
}
for (int i = 0; i < Y.length; i++) {
C[0][i]=0;
}
// i 问题的规模(长度)
for (int i = 1; i <= X.length; i++) {
// j的值不断变化
for (int j = 1; j <= Y.length; j++) {
//X和Y的初始下标为0
if(X[i-1]==Y[j-1]) {
C[i][j]=C[i-1][j-1]+1;
B[i][j]="删除x和y";
}else {
if(C[i][j-1]>C[i-1][j]) {
C[i][j]=C[i][j-1];
B[i][j]="删除y";
}else {
C[i][j]=C[i-1][j];
B[i][j]="删除x";
}
}
}
}
}
//输出最长公共子序列
public static void maxSubsequence(int i,int j) {
if(i==0||j==0) {
return ;
}
if("删除x和y".equals(B[i][j])) {
list.add(X[i-1]);
i--;
j--;
}else if("删除x".equals(B[i][j])){
i--;
}else if("删除y".equals(B[i][j])) {
j--;
}
maxSubsequence(i, j);
}
时间复杂度
算法时间复杂度为O(mn)