最长公共子序列问题

本文最后更新于:2024年3月18日 晚上

最长公共子序列问题

问题分析

  • 给定两个序列 X = { x1, x2, …, xm }和 Y = { y1, y2, …, yn },找出 X 和 Y 的最长公共子序列。

算法分析

  • 设序列 X = { x1, x2, …, xm }和 Y = { y1, y2, …, yn }的最长公共子序列为 Z = { z1, z2, …, zk },则。
    • 若 xm = yn,则 zk = xm = yn,且 Zk-1是 Xm-1和 Yn-1的最长公共子序列。
    • 若 xm != yn,且 zk != xm,则 Z 是 Xm-1和 Y 的最长公共子序列。
    • 若 xm != yn,且 zk != yn,则 Z 是 X 和 Yn-1的最长公共子序列。
  • 其中 Xm-1 = { x1, x2, …, xm-1 }, Yn-1 = { y1, y2, …, yn-1 }, Z = { z1, z2, …, zk-1 }

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class Solution {

public static void main(String[] args) {
int[] x = {30, 35, 12, 5, 11, 20, 25};
int[] y = {30, 35, 15, 5, 10, 20, 25};
int m = x.length;
int n = y.length;
int[][] c = new int[m + 1][n + 1];
int[][] b = new int[m + 1][n + 1];
Solution solution = new Solution();
solution.LCSLength(x, y, c, b);
System.out.println("最优值:");
System.out.println("---------------c[i][j]-----------------");
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
System.out.printf("%6d", c[i][j]);
}
System.out.println();
}
System.out.println("---------------b[i][j]-----------------");
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
System.out.printf("%6d", b[i][j]);
}
System.out.println();
}
System.out.println("---------------最优解-----------------");
solution.LCS(m, n, x, b);
}

public void LCSLength(int[] x, int[] y, int[][] c, int[][] b) {
int m = x.length;
int n = y.length;
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] = 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;
}
}
}
}

public void LCS(int i, int j, int[] x, int[][] b) {
if (i == 0 || j == 0) return;
if (b[i][j] == 1) {
LCS(i - 1, j - 1, x, b);
System.out.print(x[i - 1] + " ");
} else if (b[i][j] == 2) {
LCS(i - 1, j, x, b);
} else if (b[i][j] == 3) {
LCS(i, j - 1, x, b);
}
}

}
  • LCSLength(int[] x, int[] y, int[][] c, int[][] b) :计算最长公共子序列最优值。
    • int x:序列 X
    • int y:序列 Y
    • int[][] c: c[i][j] 存储 Xi和 Yj的最长公共子序列的长度。
    • int b[i][j]: b[i][j] 记录 c [i][j] 的值是由哪一个子问题的解得到的,其中 1 代表 左上, 2 代表 , 3 代表
  • LCS(m, n, x, b):计算最长公共子序列最优解。
    • int m:序列 X 的长度。
    • int n:序列 Y 的长度。
    • int x:序列 X
    • int b[i][j]: b[i][j] 记录最优值是由哪一个子问题的解得到的,其中 1 代表 左上, 2 代表 , 3 代表

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!