一、作用
常用于解决字符串的相似度。
二、概念
举个例子,cnblogs这个字符串中子序列有多少个呢?很显然有27个,比如其中的cb,cgs等等都是其子序列,我们可以看出
子序列不见得一定是连续的,连续的那是子串。
我想大家已经了解了子序列的概念,那现在可以延伸到两个字符串了,那么大家能够看出:cnblogs和belong的公共子序列吗?
在你找出的公共子序列中,你能找出最长的公共子序列吗?
从图中我们看到了最长公共子序列为blog,仔细想想我们可以发现其实最长公共子序列的个数不是唯一的,可能会有两个以上,
但是长度一定是唯一的,比如这里的最长公共子序列的长度为4。
三、解决方案
步骤一:刻画最长公共子序列递归式
定义X的第i前缀为Xi={x1,x2,x3,…xi}现有两个序列X={x1,x2,x3,…xm},Y={y1,y2,y3,….,yn},设一个C[i,j]: 保存Xi与Yj的LCS的长度。所以得出递归方程为:
步骤二:计算LCS长度
步骤三:构造LCS
四、java实现
/**
* LCS
*
* @author lzn
*
*/
public class LCS {
/**
* 计算最长公共子序列长度
*
* @param X
* @param Y
* @return 最长公共子序列长度
*/
public int LCS_LENGTH(String X, String Y) {
// 最长公共子序列长度
int max_length = 0;
// 字符串X的长度
int m = X.length();
// 字符串Y的长度
int n = Y.length();
// 数组c[i][j] 用来保存Xi与Yj的LCS的长度
int[][] c = new int[m + 1][n + 1];
// 字符串数组b[][] 用来对应计算c[i][j]是所选的子 问题的最优解 当b[i][j]=="left_up"时 表明X[i-1]==Y[j-1]为LCS的一个元素
String[][] b = new String[m + 1][n + 1];
// 初始化c[][]为0
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
c[i][j] = 0;
}
}
// 逐项比较X和Y
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
// 如果X[i]==Y[j] 应该求解X(i-1)和Y(j-1)的LCS
if (X.charAt(i - 1) == Y.charAt(j - 1)) {
c[i][j] = c[i - 1][j - 1] + 1;
// 设置b[i][j]为left_up
b[i][j] = "left_up";
} else {
// 如果如果X[i]!=Y[j] 应该求解X(i-1)和Y(j)的LCS和X(i)和Y(j-1)的LCS的较长者
if (c[i][j - 1] > c[i - 1][j]) {
// 若X(i)和Y(j-1)的LCS长度大于X(i-1)和Y(j)的LCS长度
c[i][j] = c[i][j - 1];
// 设置b[i][j]为up
b[i][j] = "up";
} else {
// 若X(i-1)和Y(j)的LCS长度大于X(i)和Y(j-1)的LCS长度
c[i][j] = c[i - 1][j];
// 设置b[i][j]为left
b[i][j] = "left";
}
}
max_length = c[i][j];
}
}
// 打印结果
System.out.print("LCS: ");
PRINT_LCS(b, X, m, n);
System.out.println();
// 返回最长公共子序列长度
return max_length;
}
/**
* 构造LCS(逆序)
*
* @param b 字符串数组b[][] 用来对应计算c[i][j]是所选的子问题的最优解
* @param X 字符串X
* @param i 字符串X的长度
* @param j 字符串Y的长度
*/
public void PRINT_LCS(String[][] b, String X, int i, int j) {
if (i == 0 || j == 0) {
return;
}
if ("left_up".equals(b[i][j])) {
System.out.print(X.charAt(i - 1));
PRINT_LCS(b, X, i - 1, j - 1);
} else {
if ("up".equals(b[i][j])) {
PRINT_LCS(b, X, i, j - 1);
} else if ("left".equals(b[i][j])) {
PRINT_LCS(b, X, i - 1, j);
}
}
}
public static void main(String[] args) {
String a = "cnblogslfszcn";
String b = "belongaldfzng";
int length = new LCS().LCS_LENGTH(a, b);
System.out.println("length of LCS: " + length);
}
}