package com.java.ly2011.June;
/**
* 最长公共子序列
*
* f(na,nb) = 1 (a[na]==b[nb]) na==0||nb==0
* 0 (a[na]!=b[nb])
* f(na,nb) = 1+f(na-1,nb-1) (a[na]==b[nb]) na!=0&&nb!=0
* f(na,nb) = max{ f(na-1,nb),f(na,nb-1)} (a[na]!=b[nb]) na!=0&&nb!=0
*
* @author Acer
*
*/
public class LCS {
private static int time;
private static int getMax(int a , int b){
return a>b?a:b;
}
/**
*
*
* 从两个数组的最后一个元素开始比
* 记住每次返回个结果之前一定要把结果记录到cache中
* @param a
* @param na a数组的起点
* @param b
* @param nb b数组的起点
* @return
*/
public static int DPLCS(int[] a ,int na,int[] b ,int nb , Integer[][] cache){
time++;
if(na ==0 || nb==0) {
int result = a[na]==b[nb]?1:0;
cache[na][nb] = result;
return result;
}
else{
if(a[na]==b[nb]){
int result;
if(cache[na-1][nb-1]!=null){
result = 1 + cache[na-1][nb-1];
}
else
result = 1 + DPLCS(a, na-1, b, nb-1, cache);
cache[na][nb] = result;
return result;
}
else{
int result1;
if(cache[na][nb-1]!=null)
result1 = cache[na][nb-1];
else
result1= DPLCS(a, na, b, nb-1, cache);
int result2;
if(cache[na-1][nb]!=null)
result2 = cache[na-1][nb];
else
result2 = DPLCS(a, na-1, b, nb, cache);
int result = getMax(result1, result2);
cache[na][nb] = result;
return result;
}
}
}
/**
* 从两个数组的最后一个元素开始比
* 记住每次返回个结果之前一定要把结果记录到cache中
* @param a
* @param na a数组的起点
* @param b
* @param nb b数组的起点
* @return
*/
public static LcsInfo DPLCS2(int[] a ,int na,int[] b ,int nb , Integer[][] cache ,String[][] lssCache){
time++;
if(na ==0 || nb==0) {
int result = a[na]==b[nb]?1:0;
String lssResult =(a[na]==b[nb]?a[na]:"") +"";
cache[na][nb] = result;
lssCache[na][nb] = lssResult;
LcsInfo li = new LcsInfo();
li.num = result;
li.lcs = lssResult;
return li;
}
else{
if(a[na]==b[nb]){
int result;
String lssResult;
if(cache[na-1][nb-1]!=null){
result = 1 + cache[na-1][nb-1];
lssResult = lssCache[na-1][nb-1] + a[na];
}
else{
LcsInfo li = DPLCS2(a, na-1, b, nb-1, cache ,lssCache);
result = 1 + li.num;
lssResult = li.lcs +a[na] ;
}
cache[na][nb] = result;
lssCache[na][nb] = lssResult;
LcsInfo li = new LcsInfo();
li.num = result;
li.lcs = lssResult;
return li;
}
else{
int result1;
String lssResult1;
if(cache[na][nb-1]!=null){
result1 = cache[na][nb-1];
lssResult1 = lssCache[na][nb-1];
}
else{
LcsInfo li= DPLCS2(a, na, b, nb-1, cache ,lssCache);
result1 = li.num;
lssResult1 = li.lcs;
}
int result2;
String lssResult2;
if(cache[na-1][nb]!=null){
result2 = cache[na-1][nb];
lssResult2 = lssCache[na-1][nb];
}
else{
LcsInfo li = DPLCS2(a, na-1, b, nb, cache,lssCache);
result2 = li.num;
lssResult2 = li.lcs;
}
int result = getMax(result1, result2);
String lssResult= result==result1?lssResult1:lssResult2;
cache[na][nb] = result;
lssCache[na][nb] = lssResult;
LcsInfo li = new LcsInfo();
li.num = result;
li.lcs = lssResult;
return li;
}
}
}
public static void main(String[] args) {
int[] a = new int[]{2,4,6,7,8,5,3};
int[] b = new int[]{4,3,2,7,8,6,5};
/*
int[] a = new int[]{2,3};
int[] b = new int[]{2,3};
*/
Integer[][] cache = new Integer[a.length][b.length];
System.out.println(DPLCS(a, a.length-1, b, b.length-1, cache));
System.out.println(time);
time = 0;
cache = new Integer[a.length][b.length];
String[][] strings = new String[a.length][b.length];
LcsInfo li = DPLCS2(a, a.length-1, b, b.length-1, cache, strings);
System.out.println(li.num);
System.out.println(time);
System.out.println(li.lcs);
}
}
class LcsInfo{
public int num ;
public String lcs;
}