51nod 1478 括號序列的最長合法子段(棧-括號匹配尋找最長合法子串長度及其個數)
阿新 • • 發佈:2019-01-30
這裡有另一個關於處理合法的括號序列的問題。
如果插入“+”和“1”到一個括號序列,我們能得到一個正確的數學表示式,我們就認為這個括號序列是合法的。例如,序列"(())()", "()"和"(()(()))"是合法的,但是")(", "(()"和"(()))("是不合法的。
這裡有一個只包含“(”和“)”的字串,你需要去找到最長的合法括號子段,同時你要找到擁有最長長度的子段串的個數。
Input
第一行是一個只包含“(”和“)”的非空的字串。它的長度不超過 1000000。Output
輸出合格的括號序列的最長子串的長度和最長子串的個數。如果沒有這樣的子串,只需要輸出一行“0 1”。Input示例
)((())))(()())
6 2
題解:看錯題目了,以為是找所有合法子串個數。想了半天,發現是找最長的。 那麼就很簡單了,用一個棧維護,將沒辦法形成匹配的括號及其位置放進一個棧裡面,那麼最後棧內每兩個括號之間就有一個合法串,然後從前往後掃一遍,記錄下最長合法串長度及其個數就好了。
程式碼如下:
#include <cstdio> #include <cstring> #include <algorithm> #include <stack> using namespace std; const int maxn = 1e6+10; struct node { int id; char s; }temp; stack<node> tac; char str[maxn]; int main() { while(scanf("%s",str)!=EOF) { int len=strlen(str); int Max=0,cnt=1; while(!tac.empty()) tac.pop(); for(int i=0;i<len;++i) { if(str[i]=='(') { temp.id=i; temp.s='('; tac.push(temp); } else { if(tac.empty()) { temp.id=i; temp.s=')'; tac.push(temp); } else { temp=tac.top(); if(temp.s==')') { temp.id=i; tac.push(temp); } else tac.pop(); } } } if(tac.empty()) Max=len; else { temp=tac.top(); int L=len-temp.id-1; Max=L; while(!tac.empty()) { temp=tac.top(); tac.pop(); if(tac.empty()){ if(temp.id>Max) { Max=temp.id; cnt=1; } else if(temp.id==Max) cnt++; } else { node step=tac.top(); L=temp.id-step.id-1; if(L==Max) cnt++; else if(L>Max){ cnt=1; Max=L; } } } } if(Max==0) cnt=1; printf("%d %d\n",Max,cnt); } return 0; }