题意:
给出一个括号序列,其中有一些地方不知道,用???代替,其余的均为(((或))),可以将???替换为(((或))),是否只有一种替换的方法,是这个序列变成合法的括号序列?合法的括号序列定义为,每一个)))前都有一个(((与之匹配,并且这个(((一旦与某个)))匹配,他就不能与其他)))匹配。
tips:
提供一个括号序列合法的检验方法:令cnt=0cnt=0cnt=0,代表还未完成匹配的左括号,遇到(((则cntcntcnt++,遇到)))则cntcntcnt–,在遍历字符串过程中cntcntcnt不能是负数,并且遍历完成后cnt==0cnt==0cnt==0。
做法:
先看这个例子......??))??))?......??))??))?......??))??))?,前四个问号一定用来匹配右括号,并且最后一个问号一定是左括号,不然会使cnt<0cnt<0cnt<0。
(())??(())??(())??,当我们看到第一个问号,这个问号就一定是(((,因此当我们wh+cnt==1wh+cnt==1wh+cnt==1时,也就是匹配完所有不匹配的右括号时,刚好剩一个,这些括号时一定能确定的,在第二个例子就是看到第一个问号,此时无需匹配))),并且遇到了第一个???,wh+cnt=1+0==1wh+cnt=1+0==1wh+cnt=1+0==1,符合条件,这个时候问号前面的完成匹配,使cnt==0cnt==0cnt==0,最后一个问号修改成(((,使cnt==1cnt==1cnt==1,所以当wh+cnt==1wh+cnt==1wh+cnt==1时,cnt=1,wh=0cnt=1,wh=0cnt=1,wh=0。如此操作,到最后遍历完剩余的问号数和没匹配的括号数(包括左右括号,也就是∣cnt∣|cnt|∣cnt∣)相等时,意味所有问号一定用来匹配这些括号,是唯一的合法序列,反之则是不合法。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int read()
{
int ret=0,base=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-') base=-1;
ch=getchar();
}
while(isdigit(ch))
{
ret=(ret<<3)+(ret<<1)+ch-48;
ch=getchar();
}
return ret*base;
}
int n;
char s[200005];
void work()
{
scanf("%s",s+1);n=strlen(s+1);
int wh=0,cnt=0;
for(int i=1;i<=n;i++)
{
if(s[i]=='(') cnt++;
if(s[i]==')') cnt--;
if(s[i]=='?') wh++;
if(cnt+wh==1)
{
cnt=1;
wh=0;
}
}
if(wh==abs(cnt)) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
int main()
{
int t=1;
scanf("%d",&t);
while(t--) work();
return 0;
}
该博客主要讨论如何判断一个包含问号的括号序列是否能通过唯一的方式填充成合法的括号序列。方法是通过计数未匹配的左括号和右括号,并观察问号出现的位置。当问号的数量等于未匹配括号的数量时,可能存在唯一解。内容涉及算法设计和代码实现。

384

被折叠的 条评论
为什么被折叠?



