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()];
        }
    }
  • 相关阅读:
    基本技能训练之线程
    关于UEditor的使用配置(图片上传配置)
    PAT 乙级练习题1002. 写出这个数 (20)
    codeforces 682C Alyona and the Tree DFS
    codeforces 681D Gifts by the List dfs+构造
    codeforces 678E Another Sith Tournament 概率dp
    codeforces 680E Bear and Square Grid 巧妙暴力
    codeforces 678D Iterated Linear Function 矩阵快速幂
    codeforces 679A Bear and Prime 100 交互
    XTUOJ 1248 TC or CF 搜索
  • 原文地址:https://www.cnblogs.com/runmoxin/p/12838792.html
Copyright © 2011-2022 走看看