九度OJ 1337:寻找最长合法括号序列 (DP)

时间限制:1 秒

内存限制:32 兆

特殊判题:

提交:839

解决:179

题目描述:
给你一个长度为N的,由’(‘和’)’组成的括号序列,你能找出这个序列中最长的合法括号子序列么?合法括号序列的含义便是,在这个序列中,所有的左括号都有唯一的右括号匹配;所有的右括号都有唯一的左括号匹配。例如:((()))()()便是一个长度为10的合法括号序列,而(()))( 则不是。
需要你求解的是,找出最长的合法括号子序列的长度,同时找出具有这样长度的序列个数。
输入:
测试数据包括多个,每个测试数据包含两行:
第一行为一个整数N,其中N不会超过10^6。
第二行为一个长度为N的字符串,这个字符串由左括号'('和右括号')'组成。
输出:
对应每个测试案例,输出一行,其中包含两个整数,分别代表最长合法括号序列的长度和个数,中间由空格隔开。若没有合法的子序列存在,则返回0 1。
样例输入:
6
(())()
3
))(
样例输出:
6 1
0 1

思路:

目前自己还没做出来,先上别人写的代码,过段时间会更新成自己写的代码。

别人算法的分析:



         红色区域表示已经得到的合法括号序列。

         如上图,分别计算以第i个符号为结尾的最长合法括号序列长度,保存在maxLen[i]中

         在位置pos时,如果该位置为‘(’,显然maxLen[pos]=0;

         如果该位置为')',  我们已经得到了pos-1位置的最长合法括号序列,我们判断以pos-1 位置为结尾的最长合法括号序列的左边位置sympos上的符号是否为'(', 

        如果sympos位置上为‘(’,如图中第2步所示,则以Pos为结尾的最长合法括号序列是以pos-1位置为结果的最长合法括号序列加上sympos上的符号‘(’和pos上的符号‘)’而成,如图第3步。

         接下来还要再加上以sympos-1为结尾的最长合法括号序列,构成最终的合法括号序列。如图第4步。

         另外一个 最长合法括号序列题,不过解决算法相差很大 九度笔记之 1342:寻找最长合法括号序列II


代码:

#include <iostream>
#include <string>
using namespace std;
void getMaxLen(std::string &s){
    std::string::size_type len = s.size();
    std::string::size_type pos = 0;
    int *maxLen = new int[len]; //maxLen end at pos
    maxLen[0] = 0;
    int ml = 0;
    int ns = 0;
    for(pos = 1;pos<len;pos++){
        if(s.at(pos)=='(' )
            maxLen[pos]=0;
        else{
            int sympos = pos-1 - maxLen[pos-1];//can't use size_type becase it's unsigned if
                                               //pos-1 < maxLen[pos-1] sympos will be 0xffffffff
            if(sympos<0 || s.at(sympos)==')'){
                maxLen[pos]=0;
            }else{
                maxLen[pos] = maxLen[pos-1]+2;// add () before
                if(sympos>0){
                    maxLen[pos]+=maxLen[sympos-1];
                }
  
                if(maxLen[pos]>ml){
                    ml = maxLen[pos];
                    ns = 1;
                }else if(maxLen[pos]==ml){
                    ns++;
                }
            }
        }// else  if(s.at(pos)=='(')
    }//for
    if(ml>0)
        std::cout<<ml<<" "<<ns<<std::endl;
    else
        std::cout<<0<<" "<<1<<std::endl;
}
  
void judo(){
    int n;
    std::string s;
    while(std::cin>>n>>s){
        getMaxLen(s);
    }
}
void test(){
    std::string s= "())";
    getMaxLen(s);
}
int main() {
    //test();
    judo();
    //cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
    return 0;
}
/**************************************************************
    Problem: 1337
    User: KES
    Language: C++
    Result: Accepted
    Time:300 ms
    Memory:6452 kb
****************************************************************/


         红色区域表示已经得到的合法括号序列。

         如上图,分别计算以第i个符号为结尾的最长合法括号序列长度,保存在maxLen[i]中

         在位置pos时,如果该位置为‘(’,显然maxLen[pos]=0;

         如果该位置为')',  我们已经得到了pos-1位置的最长合法括号序列,我们判断以pos-1 位置为结尾的最长合法括号序列的左边位置sympos上的符号是否为'(', 

        如果sympos位置上为‘(’,如图中第2步所示,则以Pos为结尾的最长合法括号序列是以pos-1位置为结果的最长合法括号序列加上sympos上的符号‘(’和pos上的符号‘)’而成,如图第3步。

         接下来还要再加上以sympos-1为结尾的最长合法括号序列,构成最终的合法括号序列。如图第4步。

         另外一个 最长合法括号序列题,不过解决算法相差很大 九度笔记之 1342:寻找最长合法括号序列II

posted on 2015-11-15 12:33  梁山伯  阅读(1465)  评论(0编辑  收藏  举报

导航