本文参照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);
}
}
可能是因为水平低,对此类算法题目无感,既无使用太多的数据结构,也不考验编程能力,只是抽象,非常抽象,适合数学专业出生的同学,工程师只是负责去实现。
第五节的改进算法确实很精彩,下面详细看一看。
今天状态很差,姑且做一次搬运工,刘佳梅女士的解法