1. 程式人生 > >1478 括號序列的最長合法子段

1478 括號序列的最長合法子段

%d col lap display targe 同時 -a 宋體 www.

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 括號序列的最長合法子段