题目说要n个字符串串内随意组合以后将这些串放在一起,然后求最长的括号匹配的长度,并不要求是连续的
因为不需要是连续的,所以可以先把已经匹配好的括号加入到答案里面去,先把这些删掉,以为并不影响结果,然后最后就只剩下))))((((这些的序列,然后接下来对剩下的考虑
因为剩下的括号最多只有四种情况就是
1.只有( ((((((((
2.只有) )))))))
3.(比)多 (((((())
4.)比(多 ))))))(((
然后我们要做的就是把他们排序,既然要得到尽可能多的匹配,那就贪心去排序,每次将(放在前面,把)放在后面,然后排序规则可以这样
1.先把 ( 全放进来
2.把 ( 比 ) 多的串放在前面
3.如果两个串都是 ( 比 ) 多,那就把 ) 少的放在前面
4.如果两个都是 ( 比 ) 少,那就把 ( 多的放在前面
5.最后再把全部都是 ) 的放在后面。
然后在扫一遍,L记录我扫到这个串的时候还有多少 ( 没有匹配,然后每次尽可能多的拿去匹配掉.
#include<map> #include<set> #include<ctime> #include<cmath> #include<stack> #include<queue> #include<string> #include<vector> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define first fi #define second se #define lowbit(x) (x & (-x)) typedef unsigned long long int ull; typedef long long int ll; const double pi = 4.0*atan(1.0); const int inf = 0x3f3f3f3f; const int maxn = 100005; const int maxm = 12; using namespace std; int n, m, tol, T; struct Node { int l, r; Node () { l = r = 0; } bool operator < (Node a) const { if(r == 0) return 1; if(a.r == 0) return 0; if(l >= r && a.l < a.r) return 1; if(l < r && a.l >= a.r) return 0; if(l >= r && a.l >= a.r) return r < a.r; else return l > a.l; } }; Node node[maxn]; char str[maxn]; void init() { memset(node, 0, sizeof node); } int main() { scanf("%d", &T); while(T--) { init(); scanf("%d", &n); int ans = 0; for(int i=1; i<=n; i++) { stack<char> s; scanf("%s", str+1); int len = strlen(str+1); for(int i=1; i<=len; i++) { if(str[i] == '(') s.push(str[i]); if(str[i] == ')') { if(!s.empty() && s.top() == '(') { ans+=2; s.pop(); } else { s.push(str[i]); } } } while(!s.empty()) { char ch = s.top(); if(ch == '(') node[i].l++; else node[i].r++; s.pop(); } } sort(node+1, node+1+n); int L = 0; for(int i=1; i<=n; i++) { if(L >= node[i].r) { ans += 2*node[i].r; L -= node[i].r; } else { ans += 2*L; L = 0; } L += node[i].l; } printf("%d\n", ans); } return 0; }