本文參照July的博客,第十一章,只給出個人理解和java實現,問題說明略。
1. 窮舉
如果X{1,2,3,4...m}
y{1,2,3,4,..n}
那麼 x的所有子序列, 2^m , y的所有子序列, 2^n,窮舉的時間複雜度 O(2^(m+n))
2. 果然動態規劃其實才是重點。
此題的重點在於反證法的使用,但是個人感覺是,除非是自己推出來,否則,總是會忘記。
反證法和定尾點是解決關鍵。
目前要求 xm 和 yn的最長公共子序列,那麼定義一個數據結構,xi 和 yj的最長公共子序列 c[i,j]
然後給出遞歸式子,要麼加1,要麼繼承,
圖片來自 july的文章
這個基本不考數據結構,就考算法
參考 算法給出java代碼
import java.util.Arrays;
public class LCS {
public static void main(String[] args) {
char[] X = {'1','A','B','C','B','D','A','B'};
char[] Y = {'2','B','D','C','A','B','A'};
LCS_LENGTH(X,Y);
}
static void LCS_LENGTH(char[] X,char[] Y){
int lenOfX = X.length;
int lenOfY = Y.length;
// 存儲記錄長度
int[][] c = new int[lenOfX][lenOfY];
// c是由哪一個記錄到達的
int[][] b = new int[lenOfX][lenOfY];
for(int i=1;i<lenOfX;i++) c[i][0] = 0;
for(int j=1;j<lenOfY;j++) c[0][j] = 0;
for(int i=1;i<lenOfX;i++){
for(int j=1;j<lenOfY;j++){
if(X[i]==Y[j]){
c[i][j] = c[i-1][j-1] +1;
b[i][j] = 1; // "↖"
}
else if(c[i-1][j]>=c[i][j-1]){
c[i][j]= c[i-1][j];
b[i][j] = 2;// "↑"
}
else{
c[i][j]=c[i][j-1];
b[i][j]= 3;// "←"
}
}
}
// System.out.println(Arrays.deepToString(b));
LCS(b,X,lenOfX-1,lenOfY-1);
}
static void LCS(int[][] b, char[] X,int i , int j){
if(i==0 || j==0) return;
if(b[i][j]==1){
LCS(b,X,i-1,j-1);
System.out.print(X[i]);
}
else if(b[i][j] == 2) LCS(b,X,i-1,j);
else LCS(b,X,i,j-1);
}
}
可能是因爲水平低,對此類算法題目無感,既無使用太多的數據結構,也不考驗編程能力,只是抽象,非常抽象,適合數學專業出生的同學,工程師只是負責去實現。
第五節的改進算法確實很精彩,下面詳細看一看。
今天狀態很差,姑且做一次搬運工,劉佳梅女士的解法