1478 括号序列的最长合法子段

Posted happy_code

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1478 括号序列的最长合法子段相关的知识,希望对你有一定的参考价值。

1478 括号序列的最长合法子段

题目来源: CodeForces

基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题

这里有另一个关于处理合法的括号序列的问题。

如果插入“+”和“1”到一个括号序列,我们能得到一个正确的数学表达式,我们就认为这个括号序列是合法的。例如,序列"(())()", "()"和"(()(()))"是合法的,但是")(", "(()"和"(()))("是不合法的。

这里有一个只包含“(”和“)”的字符串,你需要去找到最长的合法括号子段,同时你要找到拥有最长长度的子段串的个数。

Input

第一行是一个只包含“(”和“)”的非空的字符串。它的长度不超过 1000000。

Output

输出合格的括号序列的最长子串的长度和最长子串的个数。如果没有这样的子串,只需要输出一行“0  1”。

Input示例

)((())))(()())

Output示例

6 2

 

 

//括号匹配,将 ( 做 1 , ) 为 -1 ,就可以得到一串数字,求出前缀和,那么,前缀和相同,并且,又端点的值是区间中最小的,即为合法序列,用单调栈维护一个上升前缀和即可。

技术分享
 1 # include <bits/stdc++.h>
 2 using namespace std;
 3 # define LL long long
 4 # define INF 0x3f3f3f3f
 5 # define MX 100005
 6 /**************************/
 7 # define BUF_SIZE 1000005
 8 # define OUT_SIZE 1000005
 9 bool IOerror=0;
10 
11 inline char nc(){
12     static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
13     if (p1==pend){
14         p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin);
15         if (pend==p1){IOerror=1;return -1;}
16         //{printf("IO error!\n");system("pause");for (;;);exit(0);}
17     }
18     return *p1++;
19 }
20 inline bool blank(char ch){return ch== ||ch==\n||ch==\r||ch==\t;}
21 inline void read(int &x){
22     bool sign=0; char ch=nc(); x=0;
23     for (;blank(ch);ch=nc());
24     if (IOerror)return;
25     if (ch==-)sign=1,ch=nc();
26     for (;ch>=0&&ch<=9;ch=nc())x=x*10+ch-0;
27     if (sign)x=-x;
28 }
29 inline void read(char *s){
30     char ch=nc();
31     for (;blank(ch);ch=nc());
32     if (IOerror)return;
33     for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch;
34     *s=0;
35 }
36 
37 const int N=1000005;
38 struct Node{
39     int dex;
40     int num;
41 };
42 char str[N];
43 int sum[N];
44 int ans[N];
45 
46 int main ()
47 {
48     read(str+1);
49     int len = strlen(str+1);
50     for (int i=1;i<=len;++i)
51     {
52         sum[i] = sum[i-1] + (str[i]==(?1:-1);
53     }
54     stack<Node> st;
55     st.push((Node){0,0});
56     ans[0]=1;
57     for (int i=1;i<=len;++i)
58     {
59         while (!st.empty()&&sum[i]<st.top().num) st.pop();
60         if (!st.empty()&&sum[i]==st.top().num)
61         {
62             Node tp=st.top(); st.pop();
63             while (!st.empty()&&sum[i]==st.top().num)
64             {
65                 tp = st.top(); st.pop();
66             }
67             int ch = i-tp.dex;
68             ans[ch]++;
69             st.push(tp);
70         }
71         else st.push((Node){i,sum[i]});
72     }
73     int mdex=0;
74     for (int i=1;i<=len;++i)
75         if (ans[i]) mdex=i;
76     printf("%d %d\n",mdex,ans[mdex]);
77     return 0;
78 }
View Code

 

 

 

 

以上是关于1478 括号序列的最长合法子段的主要内容,如果未能解决你的问题,请参考以下文章

LongestValidParentheses, 求最长合法括号子串长度-----同类问题ValidParentheses,GenerateParentheses

leetcode-----32. 最长有效括号

CSP2019 括号树

2023-03-02:给定一个数组arr,长度为n, 任意相邻的两个数里面至少要有一个被选出来,组成子序列,才是合法的! 求所有可能的合法子序列中,最大中位数是多少? 中位数的定义为上中位数, [1,

动态规划专项刷题

BZOJ4553 - [TJOI2016]序列