最长公共子序列问题是求两个序列的一个最长的公共的子序列,不一定是连续的,但是顺序必须是正确的。
S1: b e a u t y w q l o v e
S2: w e i q i n g b e a l o v e
那么他们的最长公共子序列为bealove,长度为7(测试用例)
c表用来记录最长子序列的长度,如图所示。
/**
* 最长公共子序列的动态规划算法O(mn)
* @author Qing
*
*/
public class LCS {
public static final int N = 15;
public static final int M = 12;
public static String[] s1 = {"w","e","i","q","i","n","g","b","e","a","u","l","o","v","e"};
public static String[] s2 = {"b","e","a","u","t","y","w","q","l","o","v","e"};
public static int[][] c = new int[N+1][M+1];
public static void findLCS(){
for(int i = 1; i <= N; i++){
for(int j = 1; j <= M; j++){
//当两个字符相匹配,则最长序列数目加一
if(s1[i-1] == s2[j-1]){
c[i][j] = c[i - 1][j - 1] + 1;
}
//如果两个字符不匹配,则最长序列为相邻序列中最长的那个
else if(c[i - 1][j] < c[i][j - 1]){
c[i][j] = c[i][j - 1];
}
else{
c[i][j] = c[i - 1][j];
}
}
}
}
//输出c表
public static void print(int[][] a){
int length = a.length;
int width = a[0].length;
System.out.println("length: " + length +", width: " + width);
System.out.print("/ /");
for(int k = 0; k < width - 1; k++){
System.out.print(" " + s2[k]);
}
System.out.println(" ");
for(int i = 0; i < length; i ++){
if(i > 0){
System.out.print(s1[i-1] + " ");
}
else{
System.out.print("/ ");
}
for(int j = 0; j < width; j ++){
System.out.print(a[i][j]+" ");
}
System.out.println(" ");
}
}
public static void main(String[] args){
findLCS();
print(c);
}
}
运行结果如下:
本算法及其实现参考算法之道第二版第四章动态规划