题意:
给出几个括号序列,可以对这些括号序列重新进行排序,使得连起来的括号序列里面能匹配的括号长度最长。
思路:
首先对于同一个括号序列里面的括号可以直接进行匹配,全部匹配完后,剩下的情况肯定只有三种:全是左括号,全是右括号,前面是右括号后面是左括号。
所以对这三种情况进行贪心,排序。
全是左括号的一定要往前放,全是右括号的一定要往后放。
前面是右括号后面是左括号这种情况中,左括号多的肯定要往前放,来匹配更多的后面的右括号。
在左括号多的情况中,左括号越少的越往前放,这样能增加与后面右括号多的情况的匹配数,减少左括号的浪费。
在右括号多的情况中,右括号越多的越往前放,这样右括号可以尽可能与前面的左括号匹配。
注意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;
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!