Balanced Sequence
Problem Description
Chiaki has n n strings consisting of ‘(’ and ‘)’. A string of this type is said to be balanced:
- if it is the empty string
- if A A and are balanced, AB A B is balanced,
- if A A is balanced, is balanced.
Chiaki can reorder the strings and then concatenate them get a new string t t . Let be the length of the longest balanced subsequence (not necessary continuous) of t t . Chiaki would like to know the maximum value of for all possible t t .
Input
There are multiple test cases. The first line of input contains an integer , indicating the number of test cases. For each test case: The first line contains an integer
n
n
() – the number of strings. Each of the next
n
n
lines contains a string (
1≤|si|≤105
1
≤
|
s
i
|
≤
10
5
) consisting of (' and
)’. It is guaranteed that the sum of all
|si|
|
s
i
|
does not exceeds
5×106
5
×
10
6
.
Output
For each test case, output an integer denoting the answer.
Sample Input
2
1
)()(()(
2
)
)(
Sample Output
4
2
题目概述
有n行只包含左右括号的字符串,问如何连接这些字符串可以使得匹配到的括号最多(包括本行自身含有的“()”)
解题思路
我们先算每一行字符串中含有的成对的(),并在该行中删除已配对过的“(” 和 “)”
进行完以上操作我们可以发现每行数组都只剩下多个“)” “(”。且)全在左边,(全在右边。(每个字符串都这么处理后剩下都为“)))((((((”结构的括号串。)
那么我们把剩下的字符串拼接
要想匹配到的括号最多,则尽量让每个括号都起作用了;
如果只包含左括号则把他放在最前边,如果只有右括号把他放在最后边;
可以看出左括号多于右括号的在前,反之在后;
同是左括号多于右括号的,右括号少的在前;
同是右括号多于左括号的,左括号少的在后;
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int mmax=1e5+7;
char st[mmax];
struct node
{
int l,r;
}a[mmax];
bool cmp(node x,node y)
{
if (x.r >= x.l && y.r < y.l)
return false;
if (x.r < x.l && y.r >= y.l)
return true;
//')'比'('多的放后面
//')'比'('少 比较')'少的放前面 ')'比'('多 比较'('少的放后面
if (x.r < x.l && y.r < y.l)
return x.r<y.r;
else return x.l>y.l;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,sum=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s",st);
int len=strlen(st);
a[i].l=0;
a[i].r=0;
for(int j=0;j<len;j++)
{
if(st[j]==')')
{
if(a[i].l<=0)
a[i].r++; //没有紧邻的(来配对,( 数量加一
else
{
a[i].l--; //有可以配对的(,消耗一个)。
sum++; //配对成功的组数加一
}
}
else
a[i].l++;
}
}
sort(a,a+n,cmp);
int l=0; //l表示剩余的“(”数
for(int i=0;i<n;i++)
{
if(a[i].r<=l)
{
sum+=a[i].r;
l-=a[i].r; //l减少了a[i].r个,用于配对了
}
else
{
sum+=l;
l=0; //l都用了配对了
}
l+=a[i].l; //a[i]组字符串右边全是(
}
printf("%d\n",sum*2);
}
return 0;
}