题目链接:Balanced Sequence
题意
给出 n n 个只包含左右括号的字符串,将这些字符串拼起来,要求最终拼出来的括号序列中,最长的完全匹配括号子序列的长度最长,问最长子序列长度。
输入
第一行为一个整数 ,接下去有 T T 组数据,每组数据第一行为一个整数 ,后面 n n 行每行为一个只包含左右括号的字符串 ,数据保证 |si| | s i | 的和不超过 5×106 5 × 10 6 。
输出
输出最长完全匹配子序列长度。
样例
输入 |
---|
2 1 )()(()( 2 ) )( |
输出 |
4 2 |
题解
可以发现,每个字符串中,已经匹配的左右括号,不论以任何顺序与其他字符串连接,这些已经匹配的左右括号对都不会改变,用栈模拟匹配后,最后只会剩下最前面的 l l 个
)
和最后面的 个(
,类似)))((
的形式,只有这些括号在和其他字符串匹配的时候才会产生新的括号匹配子序列。
如果字符串 a a 有 个)
和 ar a r 个(
,字符串 b b 有 个)
和 br b r 个(
,将 a a 放在 的前面(不必相邻),则会产生 x=min(ar,bl) x = min ( a r , b l ) 对新的括号匹配子序列,将 b b 放在 的前面,则会产生 y=min(br,al) y = min ( b r , a l ) 对新的括号匹配子序列,现在贪心地对所有字符串进行排序,如果 x>y x > y ,则把 a a 排在 的前面,如果 x<y x < y 大,则把 b b 排在 的前面,如果 x=y x = y ,则把含有(
个数多的放在前面,最后扫一遍整个排序拼接后的字符串,就可以计得到答案。
过题代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
#define LL long long
const int maxn = 100000 + 100;
struct Node {
int l, m, r;
Node() {
l = m = r = 0;
}
Node(int L, int M, int R) {
l = L;
m = M;
r = R;
}
};
bool operator<(const Node &a, const Node &b) {
int aa = min(a.r, b.l);
int bb = min(b.r, a.l);
if(aa == bb) {
return a.r > b.r;
}
return aa > bb;
}
int T, n;
char str[maxn];
Node node[maxn];
Node Get() {
int len = strlen(str + 1);
Node ret;
ret.l = ret.r = 0;
for(int i = 1; i <= len; ++i) {
if(str[i] == ')') {
if(ret.r != 0) {
--ret.r;
} else {
++ret.l;
}
} else {
++ret.r;
}
}
ret.m = len - ret.l - ret.r;
return ret;
}
int main() {
#ifdef Dmaxiya
freopen("test.txt", "r", stdin);
#endif // Dmaxiya
ios::sync_with_stdio(false);
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
for(int i = 0; i < n; ++i) {
scanf("%s", str + 1);
node[i] = Get();
}
sort(node, node + n);
Node tmp = node[0];
Node ll = node[0];
Node rr;
for(int i = 1; i < n; ++i) {
rr = node[i];
tmp.l = rr.l + ll.l - min(ll.r, rr.l);
tmp.r = ll.r + rr.r - min(ll.r, rr.l);
tmp.m = ll.m + rr.m + 2 * min(ll.r, rr.l);
ll = tmp;
}
printf("%d\n", tmp.m);
}
return 0;
}