最长公共子序列(LCS)网上的资料很多,而且也可以算是动态规划里面的一个基本问题,它体现了许多动态规划的特性,算法导论这本书也给出了很详细的说明。
要写好动态规划其实还是有些难度,网上也很多相关的资料,这里我也就只是想写一篇自己个人的笔记,整理下自己学的一些东西。
public class LCS {
public static int lcsR(char[] a, int m, char[] b, int n) {
// 到达叶子节点,则可以直接求解
if (m == 0 || n == 0)
return 0;
// 剪枝(1)
if (a[m-1] == b[n-1]) {
return lcsR(a, m-1, b, n-1) + 1;
} else {
return Math.max(lcsR(a, m-1, b, n), lcsR(a, m, b, n-1));
}
}
public static void main(String[] args) {
String a = "BDCABA";
String b = "ABCBDAB";
int ret = lcsR(a.toCharArray(), a.length(), b.toCharArray(), b.length());
System.out.println(ret);
}
}
public class LCS {
// 用于记录状态
public static int[][] state = null;
// 初始化状态
public static void init(int m, int n) {
state = new int[m+1][n+1];
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
state[i][j] = -1;
}
}
}
public static int lcsR(char[] a, int m, char[] b, int n) {
if (m == 0 || n == 0) {
state[m][n] = 0;
return 0;
}
if (a[m-1] == b[n-1]) {
// 通过记忆搜索进行剪枝,如果没有相关记忆,则求解该子树并保存结果
if (state[m-1][n-1] == -1)
state[m-1][n-1] = lcsR(a, m-1, b, n-1);
state[m][n] = state[m-1][n-1] + 1;
} else {
// 通过记忆搜索进行剪枝,如果没有相关记忆,则求解该子树并保存结果
if (state[m-1][n] == -1)
state[m-1][n] = lcsR(a, m-1, b, n);
if (state[m][n-1] == -1)
state[m][n-1] = lcsR(a, m, b, n-1);
state[m][n] = Math.max(state[m-1][n], state[m][n-1]);
}
return state[m][n];
}
public static void main(String[] args) {
String a = "BDCABA";
String b = "ABCBDAB";
init(a.length(), b.length());
int ret = lcsR(a.toCharArray(), a.length(), b.toCharArray(), b.length());
for (int i = 0; i <= a.length(); i++) {
for (int j = 0; j <= b.length(); j++) {
System.out.printf("%4d", state[i][j]);
}
System.out.println("");
}
}
}
public class LCS {
// 用于记录状态
public static int[][] state = null;
public static void init(int m, int n) {
state = new int[m+1][n+1];
// 只需要初始化初始解即可
for (int i = 0; i <= m; i++) {
state[i][0] = 0;
}
for (int i = 0; i <= n; i++) {
state[0][i] = 0;
}
}
public static void lcsR(char[] a, int m, char[] b, int n) {
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (a[i-1] == b[j-1]) {
state[i][j] = state[i-1][j-1]+1;
} else {
state[i][j] = Math.max(state[i-1][j], state[i][j-1]);
}
}
}
}
public static void main(String[] args) {
String a = "BDCABA";
String b = "ABCBDAB";
init(a.length(), b.length());
lcsR(a.toCharArray(), a.length(), b.toCharArray(), b.length());
System.out.println(state[a.length()][b.length()]);
}
}
public class LCS {
public static int[] state1 = null;
public static int[] state2 = null;
public static void init(int n) {
state1 = new int[n+1];
state2 = new int[n+1];
state2[0] = 0;
for (int i = 0; i <= n; i++) {
state1[i] = 0;
}
}
public static void lcsR(char[] a, int m, char[] b, int n) {
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (a[i-1] == b[j-1]) {
state2[j] = state1[j-1] + 1;
} else {
state2[j] = Math.max(state1[j], state2[j-1]);
}
}
// 移位让state1保存上一行的状态值
int[] tmp = state1;
state1 = state2;
state2 = tmp;
}
}
public static void main(String[] args) {
String a = "BDCABA";
String b = "ABCBDAB";
init(b.length());
lcsR(a.toCharArray(), a.length(), b.toCharArray(), b.length());
System.out.println(state2[b.length()]);
}
}
public class LCS {
public static int[] state1 = null;
public static int[] state2 = null;
public static char[][] c = null;
public static void init(int m, int n) {
state1 = new int[n+1];
state2 = new int[n+1];
state2[0] = 0;
for (int i = 0; i <= n; i++) {
state1[i] = 0;
}
c = new char[m+1][n+1];
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
// 字符X表示无
c[i][j] = 'X';
}
}
}
public static void lcsR(char[] a, int m, char[] b, int n) {
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (a[i-1] == b[j-1]) {
state2[j] = state1[j-1] + 1;
// N表示左上
c[i][j] = 'N';
} else {
if (state1[j] > state2[j-1]) {
state2[j] = state1[j];
// U表示上
c[i][j] = 'U';
} else if (state1[j] < state2[j-1]) {
state2[j] = state2[j-1];
// L表示左
c[i][j] = 'L';
} else {
state2[j] = state2[j-1];
// A表示上或者左
c[i][j] = 'A';
}
}
}
// 移位让state1保存上一行的状态值
int[] tmp = state1;
state1 = state2;
state2 = tmp;
}
}
public static void main(String[] args) {
String a = "BDCABA";
String b = "ABCBDAB";
init(a.length(), b.length());
lcsR(a.toCharArray(), a.length(), b.toCharArray(), b.length());
System.out.println(state2[b.length()]);
for (int i = 0; i <= a.length(); i++) {
for (int j = 0; j <= b.length(); j++) {
System.out.print(c[i][j] + " ");
}
System.out.println("");
}
}
}
4
X X X X X X X X
X A N L N L L N
X A U A A N L L
X A U N L A A A
X N A U A A N L
X U N A N L A N
X N U A U A N A
public class LCS {
public static int[] state1 = null;
public static int[] state2 = null;
public static char[][] c = null;
public static void init(int m, int n) {
state1 = new int[n+1];
state2 = new int[n+1];
state2[0] = 0;
for (int i = 0; i <= n; i++) {
state1[i] = 0;
}
c = new char[m+1][n+1];
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
// 字符X表示无
c[i][j] = 'X';
}
}
}
public static void lcsR(char[] a, int m, char[] b, int n) {
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (a[i-1] == b[j-1]) {
state2[j] = state1[j-1] + 1;
// N表示左上
c[i][j] = 'N';
} else {
if (state1[j] > state2[j-1]) {
state2[j] = state1[j];
// U表示上
c[i][j] = 'U';
} else if (state1[j] < state2[j-1]) {
state2[j] = state2[j-1];
// L表示左
c[i][j] = 'L';
} else {
state2[j] = state2[j-1];
// A表示上或者左
c[i][j] = 'A';
}
}
}
// 移位让state1保存上一行的状态值
int[] tmp = state1;
state1 = state2;
state2 = tmp;
}
}
// 构建一个解返回
public static String getRet(char[] a, int m, char[] b, int n) {
if (m == 0 || n == 0)
return "";
String ret;
if (c[m][n] == 'N') {
ret = getRet(a, m-1, b, n-1) + a[m-1];
} else if (c[m][n] == 'L') {
ret = getRet(a, m-1, b, n);
} else if (c[m][n] == 'U') {
ret = getRet(a, m, b, n-1);
} else {
// 两个方向皆可以,随便选一个
ret = getRet(a, m-1, b, n);
}
return ret;
}
public static void main(String[] args) {
String a = "BDCABA";
String b = "ABCBDAB";
init(a.length(), b.length());
lcsR(a.toCharArray(), a.length(), b.toCharArray(), b.length());
System.out.println(state2[b.length()]);
for (int i = 0; i <= a.length(); i++) {
for (int j = 0; j <= b.length(); j++) {
System.out.print(c[i][j] + " ");
}
System.out.println("");
}
System.out.println(getRet(a.toCharArray(), a.length(), b.toCharArray(), b.length()));
}
}