码迷,mamicode.com
首页 > 其他好文 > 详细

字符串整理

时间:2014-09-06 10:57:13      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   使用   ar   strong   for   div   sp   

 

 

 

最长公共子序列(longest common subsequence)

二维dp

  状态dp[i][j]表示字符串x的前缀xi和字符串y的前缀yj能够构成的最长公共子序列的长度。

  初始化:第0行和第0列的dp[i][0] 和 dp[0][j]都设为0.

  递推:dp[i][j]=dp[i-1][j-1]+1  if(x[i]==y[j]) ; dp[i][j]= max(dp[i-1][j],dp[i][j-1])  if(x[i]!=y[j])

打印路径:1. 可以用符号记录每次选择的方向,然后从dp[m][n]向前根据符号递归打印路径。 

     2. 可以不用记录选择方向,每次根据dp[i][j] 与 d[i-1][j-1],dp[i-1][j],dp[i][j-1]的关系找出路径。

      两者打印复杂度都是O(m+n)。

空间优化:因为计算dp[i][j]只依赖于前面的一行和一列,所以可以用dp[2][n]的空间就够了,循环使用。

 

public class StringConclude {

    public static int LCS(String x, String y) {
        int m = x.length();
        int n = y.length();
        int[][] dp = 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)) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                    path[i][j] = \\;
                } else if (dp[i - 1][j] >= dp[i][j - 1]) {
                    path[i][j] = |;
                    dp[i][j] = dp[i - 1][j];
                } else {
                    path[i][j] = -;
                    dp[i][j] = dp[i][j - 1];
                }

            }
        }

        printLCS(path, x, m, n);
        System.out.println();

        printLCS(dp, x, m, n);
        System.out.println();

        return dp[m][n];

    }

    private static void printLCS(int[][] dp, String x, int i, int j) {
        if (i == 0 || j == 0)
            return;
        int maxIdx = myMaxIdx(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]);
        if (maxIdx == 0) {
            printLCS(dp, x, i - 1, j - 1);
            System.out.print(x.charAt(i - 1));
        } else if (maxIdx == 1) {
            printLCS(dp, x, i - 1, j);
        } else {
            printLCS(dp, x, i, j - 1);
        }

    }

    private static int myMaxIdx(int a, int b, int c) {
        int max = a;
        int maxIdx = 0;
        if (b > max) {
            max = b;
            maxIdx = 1;
        }
        if (c > max) {
            max = c;
            maxIdx = 2;
        }
        return maxIdx;
    }

    private static void printLCS(char[][] path, String x, int i, int j) {
        if (i == 0 || j == 0)
            return;
        if (path[i][j] == \\) {
            printLCS(path, x, i - 1, j - 1);
            System.out.print(x.charAt(i - 1));
        } else if (path[i][j] == |)
            printLCS(path, x, i - 1, j);
        else
            printLCS(path, x, i, j - 1);

    }

    public static void main(String[] args) {
        System.out.println(LCS("abcbdab", "bdcaba"));
        System.out.println(LCS("aaaa", "aaaa"));
        System.out.println(LCS("abab", "baba"));

    }
}

 

 

最长公共子串(longest common substring

二维dp

  状态dp[i][j]表示字符串x以x[i]结尾的子串和字符串y以y[j]结尾的子串能构成的最长公共子串的长度。

  初始化:第0行和第0列的dp[i][0] 和 dp[0][j]都设为0.

  递推:dp[i][j]=dp[i-1][j-1]+1  if(x[i]==y[j]) ; dp[i][j]= 0  if(x[i]!=y[j])

打印路径:只需记录最长的情况下结尾的坐标即可,因为是连续的,所以可以根据最长长度向前找到子串。

空间优化:因为计算dp[i][j]只依赖于前面的一行和一列,所以可以用dp[2][n]的空间就够了,循环使用。

    public static int LCSubstring(String x, String y) {
        int m = x.length();
        int n = y.length();

        int[][] dp = new int[m + 1][n + 1];
        int res = 0;
        int xTailIdx = -1;

        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (x.charAt(i - 1) == y.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                    if (dp[i][j] > res) {
                        res = dp[i][j];
                        xTailIdx = i;
                    }

                } else {
                    dp[i][j] = 0;
                }

            }
        }

        // print the result
        System.out.println(x.substring(xTailIdx - res, xTailIdx));

        return res;

    }

 

字符串整理

标签:style   blog   color   使用   ar   strong   for   div   sp   

原文地址:http://www.cnblogs.com/jdflyfly/p/3959179.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!