Description
Uncle-lu有一个括号序列(一个全是左括号与右括号的序列),我们都知道左括号和右括号作为一对括号称为一对匹配,但是右括号和左括号作为一对括号就不能称作一对匹配。比如说")(","(()",")()“等这类序列中存在不能组成的匹配的括号,称该序列为非法序列。但是如”(())","(()())“等这类所有括号都能找到与之匹配的序列,就称该序列为合法序列。Uncle-lu想让你帮帮他看一下他现在的这个序列是否为合法序列。
Input
第一行为一行长度为nnn的括号序列
Output
如果是合法序列输出"Yes”(不包含双引号),如果不是合法序列输出"No"(不包含双引号)
Sample Input 1
()())
Sample Output 1
No
Hint
对于100%的数据:n<10000
Time Limit
1000MS
Memory Limit
256MB
分析:左括号和右括号之间的匹配关系,就类似正数和负数之间的相互抵消关系,只不过左括号要比右括号先出现才能匹配。因此遍历括号序列时不妨用+1表示出现一个左括号,-1表示出现一个右括号,将数据记录在一个数组里,并求前缀和。易知最后一个前缀和为0表示左括号和右括号数相等,不为零则不相等。但是这样还没结束,还需要判断左括号、右括号的数目虽然相等,却有一对或多对括号没有按照正确顺序出现的情况,经过分析不难发现如果有右括号比左括号先出现,前缀和序列里就会有负数,例如:
( ) ) (
1 -1 -1 1
1 0 -1 0
所以再求出前缀和序列后,要做两个判断:前缀和序列中是否有负数,前缀和序列最后一项是否为0,且顺序不能颠倒,因为那样就不能判断出左右括号数相等但是左右括号顺序不对的情况。
参考代码:
#include<stdio.h>
int n=0;//序列长度
int flag=1;//序列合法标志
char str[10002];//括号序列
int sum[10001];//前缀和数组
int main()
{
scanf("%s",str+1);
sum[0]=0;
char *s=str+1;
while(*s)//计算括号序列长度
{
s++;
n++;
}
for(int i=1;i<=n;i++)
{
sum[i]=0;//初始化
//出现左括号则+1,出现右括号则-1
str[i]=='('?sum[i]=1:sum[i]=-1;
sum[i]+=sum[i-1];//求前缀和
}
for(int i=1;i<=n;i++)//判断左右括号顺序是否合法
{
if(sum[i]<0){
flag=0;
break;
}
}
if(sum[n]){//判断左右括号数是否相等
flag=0;
}
if(flag){
printf("Yes");
}else{
printf("No");
}
return 0;
}