zoukankan      html  css  js  c++  java
  • 网易编程-最长公共子括号序列

    一个合法的括号匹配序列被定义为:
    1. 空串""是合法的括号序列
    2. 如果"X"和"Y"是合法的序列,那么"XY"也是一个合法的括号序列
    3. 如果"X"是一个合法的序列,那么"(X)"也是一个合法的括号序列
    4. 每个合法的括号序列都可以由上面的规则生成
    例如"", "()", "()()()", "(()())", "(((()))"都是合法的。
    从一个字符串S中移除零个或者多个字符得到的序列称为S的子序列。
    例如"abcde"的子序列有"abe","","abcde"等。
    定义LCS(S,T)为字符串S和字符串T最长公共子序列的长度,即一个最长的序列W既是S的子序列也是T的子序列的长度。
    小易给出一个合法的括号匹配序列s,小易希望你能找出具有以下特征的括号序列t:
    1、t跟s不同,但是长度相同
    2、t也是一个合法的括号匹配序列
    3、LCS(s, t)是满足上述两个条件的t中最大的
    因为这样的t可能存在多个,小易需要你计算出满足条件的t有多少个。

    如样例所示: s = "(())()",跟字符串s长度相同的合法括号匹配序列有:
    "()(())", "((()))", "()()()", "(()())",其中LCS( "(())()", "()(())" )为4,其他三个都为5,所以输出3.

    题目分析:

    题目有点长,得仔细读清楚。比如这里的子序列定义为S中移除零个或者多个字符得到的序列,并不是s中连续的字符组成的。。

    首先要观察到,两个合法括号序列的LCS最大为s-1。所以就不用再找出最大长度了,因为找出最大长度工作量很大。

    这题我自己的做法是先求出了所有的符合1,2的括号序列。再找出LCS是s-1的。超时

    这题先满足第三个条件最重要。。

    求所有括号序列时,先确定有多少对括号n,根据n-1对括号的结果构建当前所有序列。对上一个结果中所有序列进行左加"()",右加"()",和"("  ")"操作。因为前面左加和右加可能会出现重复,所以想到用set存上一个的结果。但是因为还是遍历上一个结果并且删除,然后存入新的,set不合适,想到用队列,每遍历有个就是删除一个了。

    package com.xiaojiang.sort;
    
    import java.util.*;
    public class Main{
        public static void main(String[] args){
            Scanner sc=new Scanner(System.in);
            while(sc.hasNext()){
                String s=sc.nextLine();
                int n=s.length()/2;
                LinkedList<String> q=new LinkedList<>(); //队列
                q.add("()");
                int count=0;
    //
    for(int i=2;i<=n;i++){ int size=q.size(); for(int j=0;j<size;j++){ String str=q.poll(); q.add(str+"()"); if(!q.contains("()"+str))//去除重复的结果。 q.add("()"+str); q.add("("+str+")"); } } q.remove(s); for(String ss:q){ if(isLCS(s,ss)) count++; } System.out.println(count); } } public static boolean isLCS(String s,String t){ for(int i=0;i<s.length();i++){ for(int j=0;j<t.length();j++){ if((s.substring(0,i)+s.substring(i+1)).equals(t.substring(0,j)+t.substring(j+1))) { return true; } } } return false; } }

    因为题目不需要计算出所有括号序列,所以上面方法很明显不是好方法。

    首先我们要知道最大LCS是|s|-1。我们只要遍历原始字符串s,去除其中一个字符,将该字符插入到剩下字符串的每个位置,如果插入后的新字符串合法(是匹配括号字符串序列),那表明找到一个符合要求的。添加到set中,set存的是LCS为|s|-1的序列。

    最后的结果要 - 1 ,因为插入的位置会和删除的位置相同,就是原始字符串了。

    import java.util.*;
    public class Main{
        public static void main(String[] args){
            Scanner sc=new Scanner(System.in);
            while(sc.hasNext()){
                String s=sc.nextLine();
                char[] c=s.toCharArray();
                HashSet<String> set=new HashSet<>();
                for(int i=0;i<s.length();i++){
                    char e=c[i];
                    String b1=s.substring(0,i)+s.substring(i+1);
                    for(int j=0;j<s.length();j++){
                        String b2=b1.substring(0,j)+e+b1.substring(j);
                        if(isLegal(b2)) set.add(b2);
                    }
                }
                System.out.println(set.size()-1);
            }
        }
        public static boolean isLegal(String s){
            Stack<Character> stack=new Stack<>();
            if(s.charAt(0)==')') return false;
            stack.push('(');
            for(int i=1;i<s.length();i++){
                if(stack.isEmpty()){
                    if(s.charAt(i)=='(') stack.push('(');
                    else return false;
                }else{
                    if(s.charAt(i)=='(') stack.push('c');
                    else{
                        char c=stack.pop();
                        if(c==')') return false;
    
                    }
                }
            }
            return stack.isEmpty();
        }
    }
  • 相关阅读:
    hdu 5400 Arithmetic Sequence(模拟)
    hdu 5402 Travelling Salesman Problem(大模拟)
    hdu 5009 Paint Pearls (dp)
    poj 1236 Network of Schools(tarjan+缩点)
    hdu 3836 Equivalent Sets(tarjan+缩点)
    编程之美2015初赛第一场 hihoCoder #1156 : 彩色的树(染色问题)
    hdu 2807 The Shortest Path(矩阵+floyd)
    The Unique MST (判断是否存在多个最小生成树)
    Advanced Fruits(好题,LCS的模拟)
    Dark roads(kruskal)
  • 原文地址:https://www.cnblogs.com/xiaolovewei/p/8540699.html
Copyright © 2011-2022 走看看