zoukankan      html  css  js  c++  java
  • 最长公共子序列

    题目描述:

      有两个字符串,求这两个字符串的最长的公共子序列的长度(一般情况下,默认是求公共子序列的长度)。

    在刷题的过程中页有遇到这样的要求:求公共子序列的长度,并输出最长公共子序列。 

    问题说明:

      如下的代码中,虽然成功的输出了公共子序列,但是总感觉有些不足之处。因为在自己编写的两个字符串中,存在长度相同的最长公共子序列。

    带来的问题就是,我们输出的子序列不具有唯一性。在不同的编程题目中,有可能会和最终的结果出现差异。可以调整一下方法中的参数,使用不

    同的字符串作为方法的参数,得到的结果也是不同的。 

    特点分析:

      关于两个字符串的最长公共子序列,特点是子序列的字符在原来的字符串中的顺序是一致的,但是并不要求所有的字符都是连续的。 

    数据结构:

      假设Z是str1和str2的公共子序列

      str1的长度我们用x来表示

      str2的长度我们用y来表示

      建立状态转换矩阵为dp[i][j],用来表示两个字符串的最长公共子序列的长度。

      通过分析题目我们可以得到下面的三个结论:

        当str1下标为i的字符刚好等于str2下标为j的字符dp[i][j] = dp[i -1][j -1] + 1

        当str1的第i个字符和str2的第j个字符不相同的时候,那么dp[i][j] 的值就是dp[i -1][j]和dp[i ][j -1]中最大的那个

      通过记录每次得到公共字符的某种情况,可以反推得到这个字符。

    示例代码如下:

    public class LCSS {
        public static final int THIS = 1;
        public static final int UP = 2;
        public static final int LIFT = 3;
        public static void main(String[] args) {
            String str1 = "abcdcfe";
            String str2 = "abcfedc";
            int len1 = str1.length();
            int len2 = str2.length();
            int[][] dp = new int[len1+1][len2+1];
            int[][] status = new int[len1+1][len2+1];// 保存确定最大公共子序列时的三个状态,方便后续查找出对应的字符
            int res = getLCS(str1,str2,dp,status);
            System.out.println(res);
            print_LCS(len1,len2,str1,status);
        }
    
        private static void print_LCS(int len1,int len2,String str1, int[][] status) {
    
            if (len1 == 0 || len2 == 0){
                return;
            }
            if (status[len1][len2] ==THIS){
                print_LCS(len1-1,len2-1,str1,status);
                System.out.print(str1.charAt(len1-1));
            }else if(status[len1][len2] ==UP){
                print_LCS(len1,len2-1,str1,status);
            }else{
                print_LCS(len1-1,len2,str1,status);
            }
        }
    
        private static int getLCS(String str1, String str2, int[][] dp, int[][] status) {
            for (int i =0;i<=str1.length(); i++){ // 在状态转换矩阵中,第一行的值是已知的.都是0
                dp[i][0] = 0;
                status[i][0] = 0;
            }
            for (int j=0;j<=str2.length(); j++){ // 在状态转换矩阵中,第一列的值是已知的.都是0
                dp[0][j] = 0;
                dp[0][j] = 0;
            }
            for (int i = 1; i<=str1.length(); i++){
                for (int j =1;j<=str2.length();j++){
                    if(str1.charAt(i-1) == str2.charAt(j-1)){
                        dp[i][j] = dp[i-1][j-1]+1;
                        status[i][j] = THIS;
                    }else{
                        if(dp[i-1][j]<=dp[i][j-1]){
                            dp[i][j] = dp[i][j-1];
                            status[i][j] = UP;
                        }else{
                            dp[i][j] = dp[i-1][j];
                            status[i][j] = LIFT;
                        }
                    }
                }
            }
            return dp[str1.length()][str2.length()];
        }
    }
  • 相关阅读:
    使用twisted.web实现代理服务器
    django signal 浅析
    python 中接口的实现
    浅析django的abstract,proxy, managed
    python-twisted系列(1)
    postgresql 函数demo
    django 1.5+ 权限设计浅析
    django 1.7 新特性 --- data migration
    BZOJ 3670 [Noi2014]动物园 (KMP)
    BZOJ 1029 [JSOI2007]建筑抢修 (贪心 + 优先队列)
  • 原文地址:https://www.cnblogs.com/runmoxin/p/12838792.html
Copyright © 2011-2022 走看看