data structure and algorithms

动态规划之Longest common subsequence

2020-01-24  本文已影响0人  spraysss

一个序列的子序列只需要维持序列的顺序不变,不需要连续:
比如序列X

ABCBDAB

序列Y

BDCABA

其中一个最大公共子序列为BCBA,其长度为4

使用c[i,j]表示(x_1,x_2....x_i)(y_1,y_2...y_j) 的最长公共子序列的长度。

c[i,j]=\begin{cases} 0 \space if \space \space i =0 \space or \space j = 0\\ c[i-1,j-1]+1\space \space if\space \space i,j>0 \space \space and \space \space x_i=y_j\\ max(c[i-1,j],c[i,j-1]) \space \space if\space \space i,j>0 \space \space and \space \space x_i \neq y_j \end{cases}

这个满足了dp的两个要素:

dp图

java code

import java.util.Arrays;

/**
     B  D  C  A  B  A
  0, 0, 0, 0, 0, 0, 0
A 0, 0, 0, 0, 1, 1, 1
B 0, 1, 1, 1, 1, 2, 2
C 0, 1, 1, 2, 2, 2, 2
B 0, 1, 1, 2, 2, 3, 3
D 0, 1, 2, 2, 2, 3, 3
A 0, 1, 2, 2, 3, 3, 4
B 0, 1, 2, 2, 3, 4, 4
 */
public class LCS {
    public static void doLCS(String X, String Y) {
        int m = X.length();
        int n = Y.length();
        String Z = "";
        int[][] c = new int[m + 1][n + 1];
        char[][] path = new char[m + 1][n + 1];
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (X.charAt(i - 1) == Y.charAt(j - 1)) {
                    c[i][j] = c[i - 1][j - 1] + 1;
                    path[i][j]='↖';
                } else if (c[i - 1][j] >= c[i][j - 1]) {
                    c[i][j] = c[i - 1][j];
                    path[i][j] = '←';
                } else {
                    c[i][j] = c[i][j - 1];
                    path[i][j] = '↑';
                }
            }
        }

        Arrays.stream(c).forEach(e-> System.out.println(Arrays.toString(e)));

        System.out.print("最长公共子序列:");
        printLCS(path,X,m,n);
        System.out.println();
        System.out.println("最长公共子序列长度:"+c[m][n]);


    }

    public static String s;
    public static void printLCS(char[][] b, String X, int i, int j) {
        
        if (i == 0 || j == 0) {
            return;
        }
        if (b[i][j] == '↖') {
            printLCS(b, X, i - 1, j - 1);
            System.out.print(X.charAt(i-1));
        } else if (b[i][j] ==  '←') {
            printLCS(b, X, i - 1, j);

        } else {
            printLCS(b, X, i, j - 1);
        }
    }

    public static void main(String[] args) {
        doLCS("ABCBDAB", "BDCABA");

    }
}

代码地址

https://github.com/spraysss/data-structure/blob/master/src/main/java/com/ds/dp/LCS.java

上一篇 下一篇

猜你喜欢

热点阅读