• 最长公共子序列


    题目描述:

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

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

    问题说明:

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

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

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

    特点分析:

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

    数据结构:

      假设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()];
        }
    }
  • 相关阅读:
    跨表修改数据|查询修改数据|两表联合修改数据
    .net oracle 连接
    型材优化截取初步代码
    JQuery.getJSON 从aspx页面返回JSON数据 .
    asp.net form验证
    ASP.NET读取纯真IP数据库QQWry.Dat,得到地址名称
    防止PHP木马,应在PHP.INI里禁止的一些函数
    sqlserver2005中的数据库日志收缩
    jquery.pagination.js分页插件的运用
    ASP.NET前台代码绑定后台变量方法总结
  • 原文地址:https://www.cnblogs.com/runmoxin/p/12838792.html
Copyright © 2020-2023  润新知