题意:给定n个字符串,n的大小在1e5左右,字符串的长度也是1e5,字符串仅由‘(’或‘)’组成,合法串可以不是连续的,将这n个串按照一定的顺序排列起来,使得组合之后的字符串的合法串的长度最长。n*len的大小是1e6
思路:首先n*len的处理出来每一个字符串中合法的长度,处理的办法可以参考之前栈的想法,每遇见一个')',就判断前面‘(’的个数,只要不为0,此时就可以合成一个合法串,处理完之后可以得到剩下的‘)’和‘(’的个数,然后所有的n个串进行排序,最后将这些))((())((。。。。。))(((的串连接起来即可,排序的方式是)少(多的放在前面,反之放在后面,如果差不多的话,就根据))排序。
代码如下:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> using namespace std; const int maxn = 100005; int t; int n; char s[maxn]; struct NODE { int l; int r; int sum; bool operator < (const NODE &b) const { if(l>=r && b.l<=b.r) return false; else if(l<=r && b.l>=b.r) return true; else if(l>=r && b.l>=b.r) return r>=b.r; else if(l<=r && b.l<=b.r) return l<=b.l; } } node[maxn]; int main() { scanf("%d", &t); while( t-- ) { scanf("%d", &n); for(int cnt=0; cnt<n; cnt++) { scanf("%s", s); int len = strlen(s); node[cnt].l = node[cnt].r = node[cnt].sum = 0; for(int i=0; i<len; i++) { if(s[i] == ')') { if(node[cnt].r > 0) { node[cnt].r --; node[cnt].sum ++; } else { node[cnt].l++; } } else { node[cnt].r++; } } } sort(node, node+n); int ans; int now; ///now记录现在有多少个‘(’ ans = now = 0; for(int i=0; i<n; i++) { ans += node[i].sum; if(node[i].l >=now) { ans += now; now = node[i].r; } else { ans += node[i].l; now -= node[i].l; now += node[i].r; } } printf("%d ", ans*2); } return 0; }