甲乙小朋友的房子

甲乙小朋友很笨,但甲乙小朋友不会放弃

0%

算法-DP-最长公共子序列

子序列

有序列\(X=<x_1,x_2,...,x_m>\),另一个子序列\(Z=<z_1,z_2,...,z_k>\),且Z是按顺序从X中挑出来的。可以跳着挑。

最长公共子序列(LCS)

从两个序列X和Y中,找到最长的公共子序列。

思路

这道题有一个非常巧妙的办法。我们先定义\(c[i,j]表示X_i和Y_j\)的最长公共子序列的长度,那么:

公式没显示出来。截成图了。 \[ c[i,j] = \left\{ \begin{array}{c} 0 \text{....................................}若x=0 或 j=0\\ c[i-1,j-1]+1 \text{..................}若x_i==y_j \\ max(c[i,j-1],c[i-1,j])\text{.......} 若x_i!=y_j \end{array} \right. \]

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public int LCS(String[] s1,String [] s2){
int i,j;
int n = s1.length, m = s2.length;
int[][] c = new int[n][m];
if(s1[0] == s2[0]){c[0][0] = 1;}
for( i = 1 ; i < n ; i+=1 ){
if(s1[i] == s2[0]){c[i][0] = c[i-1][0] + 1; }
else{c[i][0] = c[i-1][0];}
}
for( j = 1 ; j < m ; j+=1 ){
if(s1[0] == s2[j]){c[0][j] = c[0][j-1] + 1; }
else{c[0][j] = c[0][j-1];}
}
for( i = 1 ; i < n ; i+=1 ){
for( j = 1 ; j < m ; j+=1 ){
if( s1[i]==s2[j] ){
c[i][j] = c[i-1][j-1] + 1;
}else{
c[i][j] = Math.max( c[i-1][j] , c[i][j-1] );

}
}
}
return c[n-1][m-1];
}