LCS是指最長公共子序列。計算2個字符串的LCS的算法,被廣泛應用於搜索引擎,文本編輯器,文本比較工具,IDE等工具中。
LCS計算基於已經證明的一種遞推關係。即:
1.當Xm == Yn時,LCS(X(m),Y(n)) = LCS(X(m-1),Y(n-1)) + Xm
2.當Xm != Yn時,LCS(X(m),Y(n)) = max( LCS(X(m-1),Y(n)), LCS(X(m),Y(n-1))
基於以上遞推關係則可以推導出LCS算法的基本要領:
1.基於遞推關係計算出LCS的長度矩陣和方向矩陣.
2.基於方向矩陣則可計算任意的X(m)序列和Y(n)序列的LCS。
什麼是方向矩陣?
簡言之,方向矩陣記錄了給定的m與n,LCS(X(m),Y(n))的計算方法。有了這個矩陣,我們就知道,LCS(X(m),Y(n))是應該轉化成上述推導式中的哪一種情況。顯然,方向矩陣共有3種方向。
import java.io.*;
class test
{
public static void main (String[] args) throws java.lang.Exception
{
char x[] = "abcdefaacff".toCharArray();
char y[] = "abdfeaacaa".toCharArray();
getStringsLCS(x,y);
}
public static int getStringsLCS(char []x, char[] y) {
int m = x.length;
int n = y.length;
int [][] c = new int[m + 1][n + 1];
int [][] b = new int[m + 1][n + 1];
for(int i = 0;i <= m; i++) {
c[i][0] = 0;
}
for(int i = 0;i <= n; i++) {
c[0][i] = 0;
}
for(int i = 0;i < m; i++) {
for(int j = 0;j < n; j++) {
if(x[i] == y[j]) {
c[i + 1][j + 1] = c[i][j] + 1;
b[i + 1][j + 1] = 0;
}
else if(c[i + 1][j] >= c[i][j + 1]) {
c[i + 1][j + 1] = c[i + 1][j];
b[i + 1][j + 1] = 1;
}
else {
c[i + 1][j + 1] = c[i][j + 1];
b[i + 1][j + 1] = 2;
}
}
}
//printArray2D(b);
StringBuilder sb = outputStringsLCS(b,x,m,n);
System.out.print(sb);
return 0;
}
static void printArray2D(int[][] c) {
for(int i = 0;i < c.length;i ++) {
for(int j = 0;j < c[0].length;j ++) {
System.out.print(c[i][j]);
}
System.out.println("");
}
}
static StringBuilder outputStringsLCS(int[][] b,char[] x, int i, int j) {
if(i == 0 || j == 0) {
return new StringBuilder();
}
StringBuilder sb;
if(b[i][j] == 0) {
sb = outputStringsLCS(b, x, i - 1, j - 1);
sb.append(x[i - 1]);
}
else if(b[i][j] == 1) {
return outputStringsLCS(b, x, i, j - 1);
}
else {
return outputStringsLCS(b, x, i - 1, j);
}
return sb;
}
}