1.定义
给定两个序列X和Y,如果序列Z既是X的子序列,也是Y的子序列,我们称Z是X和Y的公共子序列(common subsequence)。
2.定理(LCS的最优子结构)
令 X = {x1, x2, x3, ..., xm} 和 Y = {y1, y2, y3, ..., yn} 为两个序列, Z = {z1, z2, z3, ..., zk} 为 X 和 Y 的任意LCS。
1. 如果xm = yn , 则 zk = xm = yn 且 Zk-1 是 Xm-1 和 Y n-1 的一个LCS
2. 如果xm != yn ,那么 zk != xm 意味着 Z 是Xm-1 和 Yn-1 的一个LCS
3. 如果xm != yn ,那么 zk != yn 意味着Z是X和Yn-1的一个LCS
3.公式
若i = 0或j = 0, c[i, j] = 0;
若i > 0, j > 0 且 xi = yj, c[i, j] = c[i - 1, j -1] + 1;
若i>0, j>0 且xi != yj, c[i, j] = max(c[i, j - 1], c[i -1, j]);
4.代码(java实现)
public class LCS {
public static void main(String[] args) {
String[] X = {"A", "B", "C", "B", "D", "A", "B", "B", "A", "C"};
String[] Y = {"B", "D", "C", "A", "B", "A", "A", "B", "C"};
// print_Array(LCS_length(X, Y));
print_LCS(LCS_length(X, Y), X, X.length, Y.length);
}
/**
* @param X
* @param Y
* @return 子问题的最优解
*/
private static String[][] LCS_length(String[] X, String[] Y) {
int m = X.length;
int n = Y.length;
String[][] b = new String[m + 1][n + 1]; //存放子问题的最优解
int[][] c = new int[m + 1][n + 1]; //子问题最优解长度
for (int i = 0; i <= m; i++) {
c[i][0] = 0;
}
for (int j = 0; j <= n; j++) {
c[0][j] = 0;
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if(X[i - 1] == Y[j - 1]) {
c[i][j] = c[i - 1][j - 1] + 1;
b[i][j] = "↖";
} else if(c[i - 1][j] >= c[i][j - 1]) {
c[i][j] = c[i - 1][j];
b[i][j] = "↑";
} else {
c[i][j] = c[i][j - 1];
b[i][j] = "←";
}
}
}
return b;
}
/**
* 递归打印LCS
*/
private static void print_LCS(String[][] b, Object[] X, int i, int j) {
if(i == 0 || j == 0) {
return;
}
if(b[i][j].equals("↖")) {
print_LCS(b, X, i - 1, j - 1);
System.out.print(X[i - 1] + " ");
} else if (b[i][j].equals("↑")) {
print_LCS(b, X, i - 1, j);
} else {
print_LCS(b, X, i, j - 1);
}
}
private static void print_Array(String[][] b) {
for (int i = 0; i < b.length; i++) {
for (int k = 0; k < b[i].length; k++) {
System.out.print(b[i][k] + " ");
}
System.out.println();
}
}
}
5.代码运行结果
B C B A B C