题目信息
DarkDawn在乐学上出了一道给定括号序列,判断其合法性的问题。
括号序列是由左括号“(”和右括号“)”组成的非空序列。对于一个括号序列很容易判定其合法性。比如()
、(())()
、(()())
、(()(()))
、()()()
都是合法的,而)
、(
、(()
、(()))(
都是非法的。
Roark看了一眼题,立刻去饮水机处接了一杯水。
DarkDawn意识到他是在暗示这道题太水了,于是立刻把题改了改,增加了一、、难度。
给定 n 个括号序列,两两配对,问最多能组成多少对合法括号序列。(每一个括号序列只能在一对中出现)
Roark接完水回来再看了看新题,开始挠头了,快帮帮他!
输入
第一行输入整数n(1≤n≤100000)
表示有 n 个括号序列。
接下来 n 行,每行输入一个只由“(”和”)“构成的字符串 s 下標 i 。(字符串长度满足1≤si≤1e5
)
所有字符串长度总和满足≤5e5
。
输出
输出一个整数,表示最大的合法括号序列对数。
提示
第一组用例可以组成2对合法括号序列,分别是(( )())
、( )
。
测试样例
测试样例1
7
)())
)
((
((
(
)
)
2
测试样例2
2
(())
()
1
解答
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <stack>
#include <cstring>
#include <algorithm>
using namespace std;
int main()
{
//freopen("E://10.txt", "r", stdin);
int T;
//(是正的,)是负的。数字代表着拥有的个数
int Kong = 0;
int Left[100100] = { 0 };
int Right[100100] = { 0 };
cin >> T;
while (T--)
{
char str[100100];
cin >> str;
int len = strlen(str);
stack<char> s;
int a = 0;
int b = 0;
for (int i = 0; i < len; ++i)
{
if (!s.empty())
{//如果栈不是空的
if (s.top() == '(' && str[i] == ')')
{//恰好匹配
s.pop();
a--;
}
else if (s.top() == ')' && str[i] == '(')
{//续上
s.push(str[i]);
a++;
}
else if (s.top() == ')' && str[i] == ')')
{//续上
s.push(str[i]);
b++;
}
else if (s.top() == '(' && str[i] == '(')
{//续上
s.push(str[i]);
a++;
}
}
else if (s.empty())
{//如果栈是空的
if (str[i] == ')')
{
s.push(str[i]);
b++;
}
else if (str[i] == '(')
{
s.push(str[i]);
a++;
}
}
}
//判断完括号形式后进行统计
if (s.empty())
{//空的
Kong++;
}
else if (a > 0 && b > 0)
{
continue;
}
else if (b == 0 && a > 0)
{
Left[a]++;
}
else if (a == 0 && b > 0)
{
Right[b]++;
}
}
int ans = 0;
ans += Kong / 2;
for (int i = 0; i < 10010; i++)
{
if (Left[i] > 0 && Right[i] > 0)
{
ans+= min(Left[i], Right[i]);
}
}
cout << ans << endl;
return 0;
}