Regular Bracket Sequence(替换?组成完整括号问题)

看了一下百度上还没有这题的题解,那我来发一个吧,仅以镜鉴,或者纪念。

题目如下:


A bracket sequence is called regular if it is possible to obtain correct arithmetic expression by inserting characters + and 1 into this sequence. For example, sequences (())(), () and (()(())) are regular, while )(, (() and (()))( are not. Let’s call a regular bracket sequence “RBS”.

You are given a sequence s of n characters (, ), and/or ?. There is exactly one character ( and exactly one character ) in this sequence.

You have to replace every character ? with either ) or ( (different characters ? can be replaced with different brackets). You cannot reorder the characters, remove them, insert other characters, and each ? must be replaced.

Determine if it is possible to obtain an RBS after these replacements.


Input
The first line contains one integer t (1≤t≤1000) — the number of test cases.

Each test case consists of one line containing s (2≤|s|≤100) — a sequence of characters (, ), and/or ?. There is exactly one character ( and exactly one character ) in this sequence.


Output
For each test case, print YES if it is possible to obtain a regular bracket sequence, or NO otherwise}.

You may print each letter in any case (for example, YES, Yes, yes, yEs will all be recognized as positive answer).


Example

input
5
()
(?)
(??)
??()
)?(?
output
YES
NO
YES
YES
NO

翻译如下:


如果在括号序列中插入字符+和1可以获得正确的算术表达式,则该序列称为正则序列。例如,序列 (())(), () 和 (()(())) 是常规,而)((()和(()))(不是。让我们把一个常规的括号序列称为“RBS”。
给定一个由n个字符组成的序列s(,)和/或?在这个序列中恰好有一个字符(并且恰好有一个字符)。
你必须替换每个字符?用)或((不同的字符?可更换不同的托架)。您不能重新排列字符,删除它们,插入其他字符,每个?必须更换。
确定在这些替换之后是否有可能获得RBS。


输入
第一行包含一个整数t(1≤t≤1000)-测试用例的数量。
每个测试用例由一行包含s(2≤|s|≤100)-字符序列(,),和/或?在这个序列中恰好有一个字符(并且恰好有一个字符)。


输出
对于每个测试用例,如果有可能获得一个正规的括号序列,则打印YES,否则不打印}。
你可以在任何情况下打印每一个字母(例如:YES, YES, YES, YES都会被认为是肯定的回答)。


分析:
刚开始看的话,会感觉这道题很复杂,因为无法确定哪个左括号对应哪个右括号,会不会内层括号对应到外层去,再加上还有未知的?也会影响到左括号和右括号的对应关系。
但是目前我们可以确定的是,第一个符号一定是左括号,最后一个符号一定是右括号,并且所有字符的个数一定是偶数。
按照这个思路继续下去,我们其实不需要知道哪个对应哪个,因为我们只需要确定它能够完成这个对应即可。也就是说,我们只要确保括号加上问号最终能组成全部都完整的(),至于?()的改变会使括号的对应关系改变……不管它们怎样互相对应,至少他们能够组成完整的()
因此,可以写出如下代码:

#include<stdio.h>
#include<string.h>
#include<math.h>
int main()
{
    int t,len,count1,count2,count3,cha,i;
    char s[110];
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",s);
        len=strlen(s);
        if(len%2==0)		//符号总个数一定为偶数
        {
            if((s[0]=='('||s[0]=='?')&&(s[len-1]==')'||s[len-1]=='?'))		//符号首位和末尾的括号对应关系
            {
                count1=0;		//统计(的个数
                count2=0;		//统计)的个数
                count3=0;		//统计?的个数
                for(i=1;i<len-1;i++)	//len-1是因为字符数组从0开始
                {
                    if(s[i]=='(')
                        count1++;
                    else if(s[i]==')')
                        count2++;
                    else if(s[i]=='?')
                        count3++;
                }
                cha=fabs(count1-count2);	//计算两种括号之间相差的个数
                if(count3>=cha)		//如果?足够弥补所差,那么弥补完所差之后,剩余的?个数应为偶数
                {
                    count3=count3-cha;
                    if(count3%2==0)
                        printf("YES\n");
                    else
                        printf("NO\n");
                }
                else		//如果?不够所差,则直接输出NO
                    printf("NO\n");
            }
            else			//首位符号为)或末尾位为(都直接输出NO
                printf("NO\n");

        }
        else				//符号总个数为奇数,直接输出NO
            printf("NO\n");
    }
    return 0;
}

成功 Accepted

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值