描述问题
DarkDawn在乐学上出了一道给定括号序列,判断其合法性的问题。
括号序列是由左括号“(”和右括号“)”组成的非空序列。对于一个括号序列很容易判定其合法性。比如“()”、“(())()”、“(()())”、“(()(()))”、“()()()”都是合法的,而“)”、“(”、“(()”、“(()))(”都是非法的。
Roark看了一眼题,立刻去饮水机处接了一杯水。
DarkDawn意识到他是在暗示这道题太水了,于是立刻把题改了改,增加了一、、难度。
给定 n 个括号序列,两两配对,问最多能组成多少对合法括号序列。(每一个括号序列只能在一对中出现)
Roark接完水回来再看了看新题,开始挠头了,快帮帮他!
Input
第一行输入整数 n(1 ≤ n ≤ 100000)表示有 n 个括号序列。
接下来 n 行,每行输入一个只由“(”和”)“构成的字符串 si 。(字符串长度满足 1 ≤ |Si| ≤ 1e5)
所有字符串长度总和满足∑|Si| ≤ 5e5。
Output
输出一个整数,表示最大的合法括号序列对数。
Hint
第一组用例可以组成2对合法括号序列,分别是“(( )())”、“( )”。
样例
输入(1)
7
)())
)
((
((
(
)
)
输出(1)
2
输入(2)
2
(())
()
输出(2)
1
代码
#include <stdio.h>
#include <string.h>
#define MAX_LEN 100050
long long left[MAX_LEN] = {0};
long long right[MAX_LEN] = {0};
long long calc = 0;
int match(char c1, char c2) {
return (c1 == '(' && c2 == ')');
}
void simplifyString(char s[]) {
char stack[MAX_LEN];
int top_index = -1;
for (int i = 0; i < strlen(s); i++) {
if (top_index != -1 && match(stack[top_index], s[i])) {
top_index--;
} else {
stack[++top_index] = s[i];
}
}
if (top_index == -1) {
calc++;
return;
}
char c = stack[top_index];
int count = top_index + 1;
while (top_index >= 0) {
if (stack[top_index] != c) {
return;
}
top_index--;
}
if (c == '(') {
left[count]++;
} else {
right[count]++;
}
}
int main() {
int n;
char str[MAX_LEN];
scanf("%d\n", &n);
for (int i = 0; i < n; i++) {
scanf("%s", str);
simplifyString(str);
}
long long ans = calc / 2;
for (int i = 0; i < MAX_LEN; i++) {
ans += (left[i] < right[i]) ? left[i] : right[i];
}
printf("%lld\n", ans);
return 0;
}