题意
给你n个包含’(‘与’)’的字符串,可以将这些字符串任意排序,求所有排序中,子序列是正规括号序列的最大长度。
题解:
对于字符串排序,有两种解法
一
两个字符串的排序可以分成四种情况:
(1)str1左少右多 vs str2 左多右少
str2排在str1前面
(2)str1 左多右少 vs str2 左少右多
str1排在str2前面
(3)str1 左少右多 vs str2 左少右多
按左括号的数量排序
(4)其他情况按右括号的数量排
#include <bits/stdc++.h>
#define ll long long
#define pb push_back
using namespace std;
const int N=1e6+100;
char s[N];
struct node
{
int l,r;
friend bool operator <(node a,node b)
{
if(a.l<=a.r&&b.l>b.r ) return 0;
if(a.l>a.r&&b.l<=b.r) return 1;
if(a.r>=a.l&&b.r>=b.l) return a.l>b.l;
return a.r<b.r;
}
}app[N];
int main()
{
#ifdef local
freopen("D://r.txt","r",stdin);
#endif
//ios::sync_with_stdio(false);
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int sum=0;
for(int i=0;i<n;i++)
{
//cin>>str[i];
scanf("%s",&s);
int cnt1=0 ,cnt2 =0;
for(int j=0;j<strlen(s);j++)
{
if(s[j]==')')
{
if(cnt1!=0) cnt1--,sum+=2;
else cnt2++;
}
else cnt1++;
}
app[i].l=cnt1 ,app[i].r =cnt2 ;
}
sort(app,app+n);
int cnt1=0,cnt2=0;
for(int i=0;i<n;i++)
{
if(cnt1!=0)
{
int mi=min(cnt1 ,app[i].r);
sum+=mi*2 ;
cnt1-=mi;
app[i].r-=mi;
}
cnt2+=app[i].r;
cnt1+=app[i].l;
}
printf("%d\n",sum);
}
return 0;
}
二
首先我们对所有的字符串找到通过stack找到所有的串内正规括号子序列,之后剩下的串只有三种可能:
1. 只包含’(’
2. 先是一串’)’然后再是一串’(’
3. 只包含’)’
然后,按照第一类,第二类,第三类的顺序放置串。对于第二类内的排序,首先按照’(‘个数贡献正负排序,’)’个数小于’(‘个数则贡献为正,贡献是正的则排前面。然后正贡献的串,我们按照’)’个数从小到大排。负贡献的串,我们按照’(‘个数从大到小排。对于排序完的串,我们从前往后模拟记录一下即可。
#include <bits/stdc++.h>
#define ll long long
#define pb push_back
using namespace std;
const int N=1e6+100;
char s[N];
struct node
{
int l,r;
friend bool operator <(node a,node b)
{
if(a.l-a.r>=0&&b.l-b.r>=0) return a.r<b.r;
else if(a.l-a.r>=0) return 1;
else if(b.l-b.r>=0) return 0;
else return a.l>b.l;
}
}app[N];
int main()
{
#ifdef local
freopen("D://r.txt","r",stdin);
#endif
//ios::sync_with_stdio(false);
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int sum=0;
for(int i=0;i<n;i++)
{
//cin>>str[i];
scanf("%s",&s);
int cnt1=0 ,cnt2 =0;
for(int j=0;j<strlen(s);j++)
{
if(s[j]==')')
{
if(cnt1!=0) cnt1--,sum+=2;
else cnt2++;
}
else cnt1++;
}
app[i].l=cnt1 ,app[i].r =cnt2 ;
}
sort(app,app+n);
int cnt1=0,cnt2=0;
for(int i=0;i<n;i++)
{
if(cnt1!=0)
{
int mi=min(cnt1 ,app[i].r);
sum+=mi*2 ;
cnt1-=mi;
app[i].r-=mi;
}
cnt2+=app[i].r;
cnt1+=app[i].l;
}
printf("%d\n",sum);
}
return 0;
}