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

来源:互联网 发布:张学友 经典 知乎 编辑:程序博客网 时间:2024/06/07 15:00

时间限制:1 秒

内存限制:32 兆

特殊判题:

提交:839

解决:179

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

0 0