网易编程-最长公共子括号序列

一个合法的括号匹配序列被定义为:
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();
    }
}
原文地址:https://www.cnblogs.com/xiaolovewei/p/8540699.html