Bracket Sequences Concatenation Problem括号序列拼接问题(栈+map+思维)
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 n bracket sequences s1,s2,…,sn. Calculate the number of pairs i,j(1≤i,j≤n) such that the bracket sequence si+sj is a regular bracket sequence. Operation + means concatenation i.e. "()(" + ")()" = "()()()".
If si+sj and sj+si are regular bracket sequences and i≠j, then both pairs (i,j) and (j,i) must be counted in the answer. Also, if si+si is a regular bracket sequence, the pair (i,i) must be counted in the answer.
Input
The first line contains one integer n(1≤n≤3⋅105)— the number of bracket sequences. The following n lines contain bracket sequences — non-empty strings consisting only of characters "(" and ")". The sum of lengths of all bracket sequences does not exceed 3⋅105
.
Output
In the single line print a single integer — the number of pairs i,j(1≤i,j≤n)
such that the bracket sequence si+sj
is a regular bracket sequence.
Examples
Input
3
)
()
(
Output
2
Input
2
()
()
Output
4
Note
In the first example, suitable pairs are (3,1)and (2,2)
.
In the second example, any pair is suitable, namely (1,1),(1,2),(2,1),(2,2)
.
题目意思:有n个字符串,每个字符串都只有'('和')'组成,从中找出两个字符串si,sj( i ! = j)可以构成完全匹配的个数,同样如果si自身也能完全匹配也要算进去。
解题思路:所有的字符串可以分为3类:
1: 自身完美匹配型(即左括号和右括号完美匹配)
2:除去完全匹配的子串,剩下的都是左括号。
3:除去完全匹配的子串,剩下的都是右括号。
对于第一类他的个数ans=c(n,2)*A(2,2)+n(它自身构成的完美匹配),对于第二类和第3类,用map查询一遍(如果有左括号的个数等于右括号的个数,ans=(左括号的种类*右括号的种类),最后不要忘记除去2,因为我们算了两遍。
1 #include<cstdio> 2 #include<cstring> 3 #include<map> 4 #include<stack> 5 #include<algorithm> 6 #define ll long long int 7 #define MAX 300010 8 using namespace std; 9 map<ll,ll>mp; 10 char str[MAX]; 11 int main() 12 { 13 ll i,n,len,m,k; 14 ll counts,ans,sum; 15 scanf("%lld",&n); 16 getchar(); 17 m=0; 18 ans=0; 19 while(n--) 20 { 21 stack<char>s; 22 scanf("%s",str); 23 len=strlen(str); 24 for(i=0; i<len; i++) 25 { 26 if(!s.empty()) 27 { 28 if(s.top()=='('&&str[i]==')') 29 { 30 s.pop(); 31 } 32 else 33 { 34 s.push(str[i]); 35 } 36 } 37 else 38 { 39 s.push(str[i]); 40 } 41 } 42 if(s.empty())///自身完全匹配 43 { 44 m++; 45 } 46 else 47 { 48 counts=s.size(); 49 sum=0; 50 while(!s.empty()) 51 { 52 if(s.top()=='(') 53 { 54 sum++;///记录左括号个数 55 } 56 s.pop(); 57 } 58 if(sum==0)///剩下的都是右括号 59 { 60 mp[-counts]++;///负数代表右括号 61 } 62 else if(sum==counts)///栈里剩下的都是左括号 63 { 64 mp[counts]++;///正数代表左括号 65 } 66 } 67 } 68 map<ll,ll>::iterator it; 69 for(it=mp.begin(); it!=mp.end(); it++) 70 { 71 k=it->first; 72 if(mp.count(-k))///只有存在左括号数等于右括号数的才存在完美匹配 73 { 74 ans+=(ll)(it->second)*mp[-k]; 75 } 76 } 77 printf("%lld\n",ans/2+m*m); 78 return 0; 79 }