Description
D a r k D a w n在乐学上出了一道给定括号序列,判断其合法性的问题。
括号序列是由左括号“(”和右括号“)”组成的非空序列。对于一个括号序列很容易判定其合法性。比如“()”、“(())()”、“(()())”、“(()(()))”、“()()()”都是合法的,而“)”、“(”、“(()”、“(()))(”都是非法的。
R o a r k看了一眼题,立刻去饮水机处接了一杯水。
D a r k D a w n意识到他是在暗示这道题太水了,于是立刻把题改了改,增加了一、、难度。
给定 n 个括号序列,两两配对,问最多能组成多少对合法括号序列。(每一个括号序列只能在一对中出现)
R o a r k接完水回来再看了看新题,开始挠头了,快帮帮他!
解题思路
注意认真看题qwq
他说每一个串只用一次,每次是两个匹配,我还以为可以多个连成一个串
分析得我们只需要找到某一个串左右分别还剩下多少未匹配
可以利用栈这个数据结构,每次压入一个括号,如果可以与旁边的匹配,就把这两个删去,直到遍历到最后
这样的话两边都有未匹配的就无法与另一个成功匹配
再记录他左面或者右面有几个未匹配的
如果都为零则把他另计一个数
最后遍历一遍所有串,只需考虑左面为零右面需要匹配的串,一一对应找出来
再加上两面都是0的除以二
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
char c[100010];
int l[100010];
int r[100010];
int ansl[100010];
int ansr[100010];
int idx;
int main()
{
int n;
cin>>n;
int lin=0;
for(int t=1;t<=n;t++){
string s;
cin>>s;
int len=s.size();
for (int i = 0; i < len; i ++ ){
if(i==0)c[idx++]=s[i];
else {
if((c[idx-1]=='('&&s[i]==')')){
idx--;
}
else c[idx++]=s[i];
}
}
for(int i=0;i<=idx-1;i++){
//cout<<c[i];
if(c[i]==')')r[t]++;
else l[t]++;
}
idx=0;
if(l[t]&&r[t])continue;
if(!l[t]&&!r[t]){
lin++;
}
if(l[t]){
ansl[l[t]]++;
}
}
int ans=0;
for(int i=1;i<=n;i++){
if(!l[i]&&ansl[r[i]]){
ansl[r[i]]--;
ans++;
}
}
cout<<ans+lin/2<<endl;
}