package recursion;
public class LongCommonString {
/**
* 0 如果i = 0 或 j = 0;
* C[ i ,j ] = C [ i-1 , j -1] 如果 i , j > 0 Xi = Yj
* max{ C[ i , j-1] ,C[ i-1, j ]} 如果 i, j >0 并且 Xi≠Yj
*
* 核心思想:上图公式
* @param args
*/
public static void main(String[] args) {
LongCommonString lcs = new LongCommonString();
String A = "andio";
String B = "random";
int n = lcs.findLcs(A, B);
System.out.println(A+","+B+" 最长公共序列长度为:"+n);
}
public int findLcs(String A ,String B ) {
int n = A.length();
int m = B.length();
int at = -1;
int bt = -1;
char [] a = A.toCharArray();
char [] b = B.toCharArray();
int [][] dp = new int[n][m];
StringBuffer sb = new StringBuffer();
//初始化第一行;
for(int i=0;i<n;i++) {
if(a[i] == b[0]) {
at = i;//记录第一个相同的字母的下标
dp[i][0] =1;
for(int j =i+1;j<m;j++) {
dp[j][0] = 1;
}
break;
}
}
//初始化第一列
for(int i =0;i<m;i++) {
if(a[0] == b[i]) {
bt = i ;//记录第一个相同的字母的下标
dp[0][i] = 1;
for(int j = i+1;j<m;j++) {
dp[0][j] =1;
}
break;
}
}
//比较两个第一个相同的下标,取较小的相同字符加入公共序列
if(at != -1 && bt != -1 && at<bt) {
sb.append(a[at]);
}else {
sb.append(b[bt]);
}
//按照公式,填充数组的值
for(int i =1;i<n;i++) {
for(int j=1;j<m;j++) {
if(a[i] == b[j]) {
sb.append(a[i]);
dp[i][j] = dp[i-1][j-1] +1;
}else {
// i , j 都是递增且初始化过,所以dp[i-1][j],dp[i][j-1]都已经填充过
dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
}
}
}
for(int i =0;i<n;i++) {
for(int j =0;j<m;j++) {
System.out.print(dp[i][j]+" ");
}
System.out.println();
}
System.out.println("最长公共序列为:"+sb);
return dp[n-1][m-1];
}
}
运行结果:
0 1 1 1 1 1
0 1 2 2 2 2
0 1 2 3 3 3
0 1 2 3 3 3
0 1 2 3 4 4
最长公共序列为:ando
andio,random 最长公共序列长度为:4