返回
动态规划最长公共子序列(LCS)问题(Java实现)及Java应用详解
后端
2023-12-05 01:43:45
动态规划最长公共子序列(LCS)问题
问题分析
求最长公共子序列,先明白两个概念:
- 子序列:一个给定序列中删去若干元素后得到的序列
- 公共子序列:给定两个序列X,Y,当另一序列Z既是X的子序列,又是Y的子序列,则Z是X与Y的公共子序列
算法实现
基本思想
动态规划求最长公共子序列LCS的思想是:
- 把序列X和Y的第一个字符进行比较,若相等,则LCS(X,Y)=1+LCS(X[1...n], Y[1...n]),即把两个序列第一个字符删去后,求剩余子序列的LCS。
- 若不等,则LCS(X,Y)=max(LCS(X[1...n], Y),LCS(X,Y[1...n]),即取两个序列第一个字符都删去后,求剩余子序列的LCS的最大值。
Java实现
import java.util.Arrays;
public class LCS {
public static void main(String[] args) {
String X = "ABCDGH";
String Y = "AEDFHR";
int[][] c = new int[X.length() + 1][Y.length() + 1];
int[][] b = new int[X.length() + 1][Y.length() + 1];
int lcsLength = lcsLength(X, Y, c, b);
System.out.println("LCS length: " + lcsLength);
printLCS(X, Y, b);
}
public static int lcsLength(String X, String Y, int[][] c, int[][] b) {
for (int i = 1; i <= X.length(); i++) {
c[i][0] = 0;
}
for (int j = 0; j <= Y.length(); j++) {
c[0][j] = 0;
}
for (int i = 1; i <= X.length(); i++) {
for (int j = 1; j <= Y.length(); j++) {
if (X.charAt(i - 1) == Y.charAt(j - 1)) {
c[i][j] = c[i - 1][j - 1] + 1;
b[i][j] = 1;
} else {
if (c[i - 1][j] >= c[i][j - 1]) {
c[i][j] = c[i - 1][j];
b[i][j] = 2;
} else {
c[i][j] = c[i][j - 1];
b[i][j] = 3;
}
}
}
}
return c[X.length()][Y.length()];
}
public static void printLCS(String X, String Y, int[][] b) {
int i = X.length();
int j = Y.length();
StringBuilder sb = new StringBuilder();
while (i > 0 && j > 0) {
if (b[i][j] == 1) {
sb.append(X.charAt(i - 1));
i--;
j--;
} else if (b[i][j] == 2) {
i--;
} else {
j--;
}
}
System.out.println("LCS: " + sb.reverse().toString());
}
}