题意:

给出几个括号序列,可以对这些括号序列重新进行排序,使得连起来的括号序列里面能匹配的括号长度最长。

思路:

首先对于同一个括号序列里面的括号可以直接进行匹配,全部匹配完后,剩下的情况肯定只有三种:全是左括号,全是右括号,前面是右括号后面是左括号。

所以对这三种情况进行贪心,排序。

全是左括号的一定要往前放,全是右括号的一定要往后放。

前面是右括号后面是左括号这种情况中,左括号多的肯定要往前放,来匹配更多的后面的右括号。

在左括号多的情况中,左括号越少的越往前放,这样能增加与后面右括号多的情况的匹配数,减少左括号的浪费。

在右括号多的情况中,右括号越多的越往前放,这样右括号可以尽可能与前面的左括号匹配。

注意cmp函数的写法。

如果贪不出来的话,可以枚举多种排序情况,然后取最小值。

这里循环里多次用到strlen()的时候,要用变量存下来,否则会TLE。而且用G++交会RE也是很迷了。

代码:

struct node
{
    int l,r;
}p[100010];
int n;
int ans;
char a[100010];
node solve1()
{
    stack<char>s;
    int len=strlen(a);
    for(int i=0;i<len;i++)
    {
        if(s.empty()||a[i]=='('){s.push(a[i]);continue;}
        if(s.top()=='(')
        {
            ans+=2;
            s.pop();
        }
        else s.push(a[i]);
    }
    int ans1=0,ans2=0;
    while(!s.empty())
    {
        if(s.top()=='(')ans1++;
        else ans2++;
        s.pop();
    }
    return node{ans1,ans2};
}
bool cmp(node x,node y)
{
    if(x.r==0)return 1;
    if(y.r==0)return 0;
    if(x.l==0)return 0;
    if(y.l==0)return 1;
    int a=x.l-x.r,b=y.l-y.r;
    if(a>=0&&b<0)return 1;
    if(a<0&&b>=0)return 0;
    if(a>=0&&b>=0)return x.r<y.r;
    if(a<0&&b<0)return x.l>y.l;
    return 1;
}
void solve2()
{
    stack<char>s;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<p[i].r;j++)
        {
            if(s.empty())s.push(')');
            else if(s.top()=='(')
            {
                ans+=2;
                s.pop();
            }
            else s.push(')');
        }
        for(int j=0;j<p[i].l;j++)
            s.push('(');
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ans=0;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%s",a);
            p[i]=solve1();
        }
        //printf("%d\n",ans);
        //for(int i=0;i<n;i++)
        //printf("(%d,%d)\n",p[i].first,p[i].second);
        sort(p,p+n,cmp);
        solve2();
        printf("%d\n",ans);
    }
    return 0;
}

括号匹配的另一种更快的写法:

struct node
{
    int l,r;
}p[100010];
char a[100010];
bool cmp(node x,node y)
{
    if(x.r==0)return 1;
    if(y.r==0)return 0;
    if(x.l==0)return 0;
    if(y.l==0)return 1;
    if(x.l>=x.r&&y.l<y.r)return 1;
    if(x.l<x.r&&y.l>=y.r)return 0;
    if(x.l>=x.r&&y.l>=y.r)return x.r<y.r;
    if(x.l<x.r&&y.l<y.r)return x.l>y.l;
    return 1;
}
int main()
{
    int t,n,ans;
    scanf("%d",&t);
    while(t--)
    {
        ans=0;
        scanf("%d",&n);
        for(int j=0;j<n;j++)
        {
            scanf("%s",a);
            p[j].l=0;p[j].r=0;
            int len=strlen(a);
            for(int i=0;i<len;i++)
            {
                if(a[i]=='(')
                    p[j].l++;
                else
                {
                    if(p[j].l!=0)
                    {
                        ans+=2;
                        p[j].l--;
                    }
                    else p[j].r++;
                }
            }
        }
        //printf("%d\n",ans);
        //for(int i=0;i<n;i++)
        //printf("(%d,%d)\n",p[i].first,p[i].second);
        sort(p,p+n,cmp);
        int L=0;
        for(int i=0;i<n;i++)
        {
            if(L>=p[i].r)
            {
                ans+=2*p[i].r;
                L-=p[i].r;
            }
            else
            {
                ans+=2*L;
                L=0;
            }
            L+=p[i].l;
        }
        printf("%d\n",ans);
    }
    return 0;
}