zoukankan      html  css  js  c++  java
  • 最长公共子序列; 给定两个字符串,返回两个字符串的最长公共子序列(不是最长公共子字符串),可能是多个。

    最长公共子序列
    Description

    给定两个字符串,返回两个字符串的最长公共子序列(不是最长公共子字符串),可能是多个。

    Input

    输入第一行为用例个数, 每个测试用例输入为两行,一行一个字符串

    Output

    如果没有公共子序列,不输出,如果有多个则分为多行,按字典序排序。

    Sample Input 1

    1
    1A2BD3G4H56JK
    23EFG4I5J6K7
    

    Sample Output 1

    23G456K
    23G45JK
    
    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.Scanner;
    import java.util.Set;
    
    public class Q1_1 {
        private static int T;
        public static void main(String[] args) {
            Scanner in = new Scanner(System.in);
            T = in.nextInt();
            in.nextLine();
            while (T-- != 0) {
                String a = in.nextLine();
                String b = in.nextLine();
    
                Set<String> lcsSet = LCS(a, b);
    
                ArrayList<String> list = new ArrayList<>(lcsSet);
                if (list.size() == 1 && list.get(0).equals("")){
                    continue;
                }
                list.sort(String::compareTo);
                for (int i = 0; i < list.size(); i++) {
                    print(list.get(i), list.size()-1-i);
                }
            }
        }
    
        private static void print(String s, int n){
            if (T == 0 && n == 0){
                System.out.println(s);
            }else{
                System.out.println(s );
            }
        }
    
        public static Set<String> LCS(String a, String b) {
            int n = a.length(), m = b.length();
            //c[i][j]表示a长度为i和b长度为j时的最长公共子序列长度
            int[][] c = new int[n+1][m+1];
            //d[i][j]表示方向
            char[][] d = new char[n+1][m+1];
            for(int i = 1; i <= n; ++i) {
                for(int j = 1; j <= m; ++j) {
                    if(a.charAt(i-1) == b.charAt(j-1)) {
                        c[i][j] = c[i-1][j-1] + 1;
                        //左上
                        d[i][j] = '↖';
                    } else if(c[i-1][j] > c[i][j-1]){
                        c[i][j] = c[i-1][j];
                        //上
                        d[i][j] = '↑';
                    } else if(c[i-1][j] < c[i][j-1]){
                        c[i][j] = c[i][j-1];
                        //左
                        d[i][j] = '←';
                    } else {
                        c[i][j] = c[i][j-1];
                        //可向左可向右
                        d[i][j] = '┘';
                    }
    //                System.out.print(j == m ? c[i][j] + "
    ":c[i][j] + " ");
                }
            }
    //        for(int i = 0; i <= n; ++i){
    //            for(int j = 0; j <= m; ++j) {
    //                System.out.print(j == m ? d[i][j] + "
    ":d[i][j] + " ");
    //            }
    //        }
            String lcs = "";
            Set<String> lcsSet = new HashSet<>();
            backTrace(d,a,lcs,n,m,c[n][m],lcsSet);
    
            return lcsSet;
        }
    
        public static void backTrace(char[][] d, String a, String lcs, int i , int j, int maxSublen, Set<String> lcsSet){
            if(i == 0 || j == 0) {
                StringBuilder sb = new StringBuilder(lcs);
                lcs = sb.reverse().toString();
                //可能有些提早出来了,一定要判断长度是最长的,但是这样还是会有重复的字符串,所以还要做去重处理
                if (lcs.length() == maxSublen) {
                    lcsSet.add(lcs);
                }
                return;
            }
    
            switch (d[i][j]){
                case '↖':
                    lcs += a.charAt(i-1);
                    backTrace(d,a,lcs,i-1,j-1,maxSublen,lcsSet);
                    break;
                case '↑':
                    backTrace(d,a,lcs,i-1,j,maxSublen,lcsSet);
                    break;
                case '←':
                    backTrace(d,a,lcs,i,j-1,maxSublen,lcsSet);
                    break;
                case '┘':
                    backTrace(d,a,lcs,i-1,j,maxSublen,lcsSet);
                    backTrace(d,a,lcs,i,j-1,maxSublen,lcsSet);
                    break;
            }
        }
    
    }
    
    
  • 相关阅读:
    洛谷
    洛谷
    NOIP 普及组 2014 螺旋矩阵
    NOIP 普及组 2014 珠心算测验
    hdu 1114Piggy-Bank(完全背包)
    hdu 2059龟兔赛跑("01"背包)
    洛谷 P1282 多米诺骨牌("01"背包)
    洛谷 P1140 相似基因(DP)
    洛谷 P1880 [NOI1995] 石子合并(区间DP)
    洛谷 P1280 尼克的任务
  • 原文地址:https://www.cnblogs.com/billxxx/p/11768973.html
Copyright © 2011-2022 走看看