【CodeForces 990C】 Bracket Sequences Concatenation Problem
題目鏈接
luogu & CodeForces
題目描述
A bracket sequence is a string containing only characters "(" and ")".
A regular bracket sequence is a bracket sequence that can be transformed into a correct arithmetic expression by inserting characters "1" and "+" between the original characters of the sequence. For example, bracket sequences "()()", "(())" are regular (the resulting expressions are: "(1)+(1)", "((1+1)+1)"), and ")(" and "(" are not.
You are given nn bracket sequences s1,s2,…,sns1,s2,…,sn. Calculate the number of pairs i,j(1≤i,j≤n)i,j(1≤i,j≤n) such that the bracket sequence si+sjsi+sj is a regular bracket sequence. Operation ++ means concatenation i.e. "()(" + ")()" = "()()()".
If si+sjsi+sj and sj+sisj+si are regular bracket sequences and
題目翻譯(摘自luogu)
給出n個字符串,保證只包含‘(‘和‘)‘,求從中取2個字符串鏈接後形成正確的括號序列的方案數(每個串都可以重復使用)(像‘()()‘和‘(())‘這樣的都是合法的,像‘)(‘和‘(‘這樣的是不合法的)
輸入:
第一行一個整數n
第二行到第n+1行每行一個字符串
輸出:
方案數
感謝@zhaotiensn 提供翻譯
解題思路
當然,首先能想到的就是n^2枚舉,然後再O(len)進行判斷,顯然T到飛起??
然後我們想一想,先去掉O(len)的檢驗,這個套在n^2裏實在是太過分了qwq
對於每一個串,裏面有一些括號是可以直接匹配上的,那麽我們先把他們處理出來,這樣我們就不需要檢驗那麽長了。 然後我們再想想,我們從一個串的左向右掃一遍,遇到‘)’就找上一個沒有匹配的‘(’,然後把他們進行匹配,那麽最後可能還剩下一些‘(’或‘)’沒有辦法進行匹配,我們用 l 表示沒有匹配的‘(’的個數,r 表示為匹配的‘)’的個數。
那麽,如果 l 和 r 都不等於零,那麽這一個串顯然是廢的,因為你頂多在左邊或者右邊加一個串,匹配掉一個方向的括號,不可能消掉兩邊的括號。
相反的,如果 l 和 r 都等於零,那麽擁有這些性質的串相互亂放都是可以的 ,比如串A和串B滿足這個性質,則A+B和B+A都是合法的。 如果有zer個這樣的串,那就有zer^2種組合方法。
如果一個串的 l 等於零,r不等於零,那麽它和另一個r=0 且l等於它的r串就可以組合成一個完整的串。
這樣記錄一下l和r,整個掃一遍就OK了。
代碼
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 int n; 7 char s[300050]; 8 int totl[300050],totr[300050]; 9 int zer; 10 int main(){ 11 cin>>n; 12 for(register int i=1;i<=n;i++){ 13 scanf("%s",s); 14 int len=strlen(s),l=0,r=0; 15 for(register int j=0;j<len;j++){ 16 if(s[j]==‘)‘&&!l)r++; 17 else if(s[j]==‘)‘)l--; 18 else if(s[j]==‘(‘)l++; 19 } 20 if(!l&&!r)zer++; 21 else if(!l)totr[r]++; 22 else if(!r)totl[l]++; 23 } 24 long long ans=0; 25 for(register int j=1;j<=300000;j++){ 26 ans+=(long long)totr[j]*totl[j]; 27 } 28 ans+=(long long)zer*zer; 29 cout<<ans<<endl; 30 }
【CodeForces 990C】 Bracket Sequences Concatenation Problem