题意:
给定 $n$ 个括号序列,问任意组合之后最大的匹配长度是多少。
思路:
要使得匹配长度最大,那么就是尽可能多的匹配括号,那么我们就可以记录每一个序列本身不能够匹配的左括号数和右括号数;
然后对于两个序列之间,我们分情况讨论,然后排序一遍,再进行匹配一次,记录答案就好了,详情见代码注释。
1 /* 2 * @Author: windystreet 3 * @Date: 2018-08-07 08:46:12 4 * @Last Modified by: windystreet 5 * @Last Modified time: 2018-08-07 09:03:00 6 */ 7 #include<bits/stdc++.h> 8 9 using namespace std; 10 11 #define X first 12 #define Y second 13 #define eps 1e-5 14 #define gcd __gcd 15 #define pb push_back 16 #define PI acos(-1.0) 17 #define lowbit(x) (x)&(-x) 18 #define bug printf("!!!!! "); 19 #define mem(x,y) memset(x,y,sizeof(x)) 20 21 typedef long long LL; 22 typedef long double LD; 23 typedef pair<int,int> pii; 24 typedef unsigned long long uLL; 25 26 const int maxn = 1e5+2; 27 const int INF = 1<<30; 28 const int mod = 1e9+7; 29 30 struct node 31 { 32 int p,q; // 左括号,右括号 33 }s[maxn]; 34 35 bool cmp(node a, node b){ 36 if(a.q >= a.p && b.q < b.p)return false; // 当a的右括号数大于左括号数 且 b的左括号数大于右括号数,则将b排在前面 37 if(b.q >= b.p && a.q < a.p)return true; // 当a的左括号数大于右括号数 且 b的右括号数大于左括号数,则将a排在前面 38 if(a.q >= a.p && b.q >= b.p) return a.p >b.p; // 当a,b的右括号都大于左括号的时候,就将左括号多的排前面 39 return a.q<b.q; // 否则的话还是将左括号多的排前面 40 } 41 42 char str[maxn]; 43 44 void solve(){ 45 int n,ans = 0; 46 scanf("%d",&n); 47 for(int i=1;i<=n;i++){ 48 scanf("%s",str); 49 s[i].p = s[i].q = 0; 50 int len = strlen(str); 51 for(int j=0;j<len;j++){ 52 if(str[j]== '(')s[i].p++; // 记录左括号 53 if(str[j]== ')'){ 54 if(s[i].p){ // 先行在序列中匹配 55 s[i].p--;ans+=2; 56 }else s[i].q++; // 不能匹配的话就记录右括号 57 } 58 } 59 } 60 sort(s+1,s+1+n,cmp); 61 int cnt = 0; // 记录当前未匹配的左括号的数量 62 for(int i=1;i<=n;i++){ 63 if(s[i].q > cnt) s[i].q = cnt; 64 ans += s[i].q*2; // 更新当前可以匹配的答案 65 cnt -= s[i].q; 66 cnt += s[i].p; 67 } 68 printf("%d ",ans); 69 return; 70 } 71 72 int main() 73 { 74 // freopen("in.txt","r",stdin); 75 // freopen("out.txt","w",stdout); 76 // ios::sync_with_stdio(false); 77 int t = 1; 78 scanf("%d",&t); 79 while(t--){ 80 // printf("Case %d: ",cas++); 81 solve(); 82 } 83 return 0; 84 }