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 }

 

转载于:https://www.cnblogs.com/wkfvawl/p/9439539.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值