Codeforces 1709C 思维,括号序列

题意:

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

tips:

提供一个括号序列合法的检验方法:令 c n t = 0 cnt=0 cnt=0,代表还未完成匹配的左括号,遇到 ( ( ( c n t cnt cnt++,遇到 ) ) ) c n t cnt cnt–,在遍历字符串过程中 c n t cnt cnt不能是负数,并且遍历完成后 c n t = = 0 cnt==0 cnt==0

做法:

先看这个例子 . . . . . . ? ? ) ) ? ? ) ) ? ......??))??))? ......??))??))?,前四个问号一定用来匹配右括号,并且最后一个问号一定是左括号,不然会使 c n t < 0 cnt<0 cnt<0

( ( ) ) ? ? (())?? (())??,当我们看到第一个问号,这个问号就一定是 ( ( (,因此当我们 w h + c n t = = 1 wh+cnt==1 wh+cnt==1时,也就是匹配完所有不匹配的右括号时,刚好剩一个,这些括号时一定能确定的,在第二个例子就是看到第一个问号,此时无需匹配 ) ) ),并且遇到了第一个 ? ? ? w h + c n t = 1 + 0 = = 1 wh+cnt=1+0==1 wh+cnt=1+0==1,符合条件,这个时候问号前面的完成匹配,使 c n t = = 0 cnt==0 cnt==0,最后一个问号修改成 ( ( (,使 c n t = = 1 cnt==1 cnt==1,所以当 w h + c n t = = 1 wh+cnt==1 wh+cnt==1时, c n t = 1 , w h = 0 cnt=1,wh=0 cnt=1wh=0。如此操作,到最后遍历完剩余的问号数和没匹配的括号数(包括左右括号,也就是 ∣ c n t ∣ |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;
}
      
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值