题面:
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 i≠ji≠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.
The first line contains one integer n(1≤n≤3⋅105)n(1≤n≤3⋅105) — the number of bracket sequences. The following nn lines contain bracket sequences — non-empty strings consisting only of characters "(" and ")". The sum of lengths of all bracket sequences does not exceed 3⋅1053⋅105.
In the single line print a single integer — 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.
3 ) () (
2
2 () ()
4
In the first example, suitable pairs are (3,1)(3,1) and (2,2)(2,2).
In the second example, any pair is suitable, namely (1,1),(1,2),(2,1),(2,2)(1,1),(1,2),(2,1),(2,2).
题目描述:
给你n个总长度不超过3e5的“)”或“(”的字符串。当存在完整的括号“()”,则称这是完美的括号。问你从这n个选任意两个字符串并将它们相加,最多能构成多少个完美的括号。
题目分析:
首先我们可以观察到,对于每一个字符串,我们将从左到右将“(”和“)”括号进行匹配。倘若剩下的括号既有“(”又有“)”,则存在且仅存在“)(”这种字符串。而我们很容易发现,这种字符串是不可能进行匹配的,因此我们只需要排除掉这种情况即可。
而倘若不存在上述的情况,我们不难发现,此时必定仅剩下一种符号。此时,我们可以开一个桶num[i][j],使得num[i][j]++,表示j个第i种括号的数量+1。
统计完这些数据之后,我们只需从头遍历到n个字符串中最大的长度len,每一次将num[0][len]*num[1][len](假设0代表“(”;1代表“)”)加到结果去即可。
代码:
#include <bits/stdc++.h>
#define maxn 300005
using namespace std;
typedef long long ll;
ll num[2][maxn];
int main()
{
int n;
string str;
cin>>n;
ll res=0;
for(int i=0;i<n;i++){
cin>>str;
int len=str.length();
ll l=0,r=0;
for(int j=0;j<len;j++){
if(str[j]==')'){
if(l) l--;//如果匹配到右括号而前面出现过左括号则左右括号匹配
else r++;//如果匹配不出来,则右括号+1
}
else l++;
}
if(l&&r) continue;//如果左右括号均有剩余,则只可能出现“)(”的情况
if(l){
num[0][l]++;//剩余l个左括号匹配,使桶的数量+1
}
else if(r){
num[1][r]++;
}
else res++;//完全匹配
}
res*=res;//使得完全匹配能够翻倍
for(int i=1;i<maxn;i++){//统计0到最大长度的数量
res+=num[0][i]*num[1][i];
}
cout<<res<<endl;
}