算法 - 动态规划DP

LCS

定义
一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。

例如:输入两个字符串 BDCABA 和 ABCBDAB,字符串 BCBA 和 BDAB 都是是它们的最长公共子序列,则输出它们的长度 4,并打印任意一个子序列. (Note: 不要求连续)

:

public String LCS(String s1, String s2) {
        int len1 = s1.length();
        int len2 = s2.length();
        /* 状态定义 */
        int[][] dp = new int[len1+1][len2+1];
        /* 状态初始化 */
        /**
         *x/y| 0 1 2 3
         *  -|-----
         *  0| 0 0 0 0
         *  1| 0
         *  2| 0
         *  3| 0
         * */
        for (int i = 0; i < len2 + 1; i++) dp[0][i] = 0;
        for (int i = 0; i < len1 + 1; i++) dp[i][0] = 0;
        /* dp状态的推导 */
        /**
         * c[i,j] = c[i-1][j-1] + 1 , xi = yj
         * c[i,j] = max(c[i,j-1],c[i-1,j]) xi != yj
         * */
        for (int i = 0; i < len1; i++) {
            for (int j = 0; j < len2; j++) {
                if(s1.charAt(i) == s2.charAt(j)) dp[i+1][j+1] = dp[i][j] + 1;
                else dp[i+1][j+1] = Math.max(dp[i][j+1],dp[i+1][j]);
            }
        }
        for (int i = 0; i < len1 + 1; i++) System.out.println(Arrays.toString(dp[i]));
        int x = len1,y = len2;
        StringBuilder sb = new StringBuilder();
        while(x != 0 || y != 0) {
            if(dp[x][y-1] == dp[x][y]) y = y-1;
            else if(dp[x-1][y] == dp[x][y]) x = x-1;
            else {
                sb.append(s1.charAt(x-1));
                x--;
                y--;
            }
        }
        return new String(sb.reverse());
    }

猜你喜欢

转载自blog.csdn.net/qq_37873426/article/details/89417714
今日推荐