C - Bracket Sequences Concatenation Problem CodeForces - 990C

C. Bracket Sequences Concatenation Problem
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
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
inputCopy
3
)
()
(
outputCopy
2
inputCopy
2
()
()
outputCopy
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个只包含左圆括号 和 右圆括号 的字符串,从中任意选择两个字符串,可以组成合法字符串的个数是多少
合法指 例如a="(()" b="())" a+b=(()()) 这样是合法的,如果 a="(()" b="(()" a+b="(()(()" 这样是不合法的

思路:可以得出,一共有两种情况:
第一种 字符串输入进来就是合法的,那么它可以和其他合法的字符串组成 x*(x-1)+x个合法的 ,这里假设有x个合法的
如:a="()" b="()()" c="(())"
所以就有 3*2+3 =9个 分别为:aa ab ac bb ba bc cc ca cb

第二种情况:将字符串中成对的左右圆括号删去后只剩下连续的左括号或者右括号,这是设左括号的个数为 l 右括号的个数为 r 所以就有 l*r种,值得注意的是只能将左括号和右括号个数相同的字符串相乘,如 a="((" b=")" 它们之间是不可以计算种数的

具体代码如下:

#include<bits/stdc++.h>
#define LL long long
#define Max 100005
const LL mod=1e9+7;
const LL LL_MAX=9223372036854775807;
using namespace std;
string s[3*Max];
LL ans=0,lr=0;
LL L[3*Max],R[3*Max];
int Rank(char ch)
{
    if(ch=='(')
        return -1;
    if(ch==')')
        return 1;
}
int check(string str)
{
    stack<char> s;//利用栈消去成对的圆括号
    int len = str.size();
    for(int i=0; i<len; i++)
    {
        if(!s.empty() && s.top()=='(' && str[i]==')')
            s.pop();
        else
            s.push(str[i]);
    }
    if(s.size()==0)//全部消去,说明就是合法的
        return 0;
    int t=s.size();
    char ch=s.top();
    s.pop();
    while(!s.empty() && ch==s.top())//验证是否全是同方向括号
        s.pop();
    if(s.empty()){
        if(ch=='(')
            L[t]++;
        else
            R[t]++;
    }
    return 2;
}
int main()
{
    int n;
    scanf("%d",&n);
    int maxlen=0,len;
    for(int i=0; i<n; i++)
    {
        cin>>s[i];
        len=s[i].size();
        maxlen=max(maxlen,len);
        int t=check(s[i]);
        if(t==0)
            lr++;
    }
    ans+=(lr*(lr-1))+lr;
    for(int i=1;i<=maxlen;i++)
        ans+=L[i]*R[i];
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Gee_Zer/article/details/89326161