Codeforces 1709C 思维,括号序列

该博客主要讨论如何判断一个包含问号的括号序列是否能通过唯一的方式填充成合法的括号序列。方法是通过计数未匹配的左括号和右括号,并观察问号出现的位置。当问号的数量等于未匹配括号的数量时,可能存在唯一解。内容涉及算法设计和代码实现。
题意:

给出一个括号序列,其中有一些地方不知道,用???代替,其余的均为((())),可以将???替换为((())),是否只有一种替换的方法,是这个序列变成合法的括号序列?合法的括号序列定义为,每一个)))前都有一个(((与之匹配,并且这个(((一旦与某个)))匹配,他就不能与其他)))匹配。

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=1wh=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;
}
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值