1. 程式人生 > >【CodeForces 990C】 Bracket Sequences Concatenation Problem

【CodeForces 990C】 Bracket Sequences Concatenation Problem

space bracket 組合方法 記錄 AS origin cout width contain

題目鏈接

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(1i,jn)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

iji≠j, then both pairs (i,j)(i,j) and (j,i)(j,i) must be counted in the answer. Also, if si+sisi+si is a regular bracket sequence, the pair (i,i)(i,i) must be counted in the answer.

題目翻譯(摘自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