PAT乙级-1003-“我要通过”详解-为什么连题目都看不懂

首先理解题目:

第一个条件
判断字符串中是否仅有 ‘P’,‘A’, 'T’这三种字符,包含其他字符就错误

第二个条件:
任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字符’A’组成的字符串;
那么正确的有这些:

PAT
APATA
AAPATAA
AAAPATAAA
就是中间一个’A’左右加上等量的’A’(不加也可以)都是正确的。

难以理解的是第三个条件:
如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a、 b、 c 均或者是空字符串,或者是仅由字母 A 组成的字符串。
乍一看感觉蒙蒙的,那我们先代入看看,找正确字符串的代入aPbTc:
PAT —— 对于 aPbTc 来说ac是空,b是’A’。所以 PAAT 是正确的。类推出PAAAAAT中间加多少个A都是正确的
APATA —— 对于aPbTc来说,abc都是’A’。所以 APAATAA 是正确的。再类推一下,那么 APAAATAAA 是正确的。
AAPATAA —— 对于aPbTc来说,a和c是’‘AA’’,b是’A’。所以AAPAATAAAA是正确的,再类推一下,AAPAAATAAAAAA 是正确的。
推理——开头的’A’的个数 * 中间的’A’的个数 = 结尾的’A’的个数

我们结合三个条件中就能看出规律:字符串中只能有一个’P’一个’T’,且’P’要在’T’之前,中间末尾和开头可以插入’A’。
插入’A’的条件是:

  • (1)
    (开头的’A’的个数 )乘以 (中间的’A’的个数) 等于(结尾的’A’的个数)
  • (2)
    ’P’和’T’两端没有’A’,中间只要有’A’就可以('A’的个数不是0就可以)
    满足两者任意一个条件,字符串就正确

实质上,本题考察的是对字符串的操作,但是题目难于理解。遇到这类题目,我建议在草稿纸上划出字符串的种种形式,慢慢往下推理,就能快速找到规律

下面是实操代码,不太清楚的地方欢迎评论区讨论

#include<iostream>
#include<stdio.h>
#include<string.h>

using namespace std;

bool isRight(string str){							//判断传入的字符串是否正确 ,传入的参数是所需判断的字符串 
	int len=str.length();
	int a=0,b=0;									//辅助变量 ,a表示字符'P'的个数,b表示字符'T'的个数 
	for(int i=0;i<len;++i){							//遍历字符串 
		if(str[i]=='P'||str[i]=='T'||str[i]=='A'){	//判断字符只能是'P','A','T'的组合 
			if(str[i]=='P'){						//统计'P'的个数 
				++a; 	
			}
			if(str[i]=='T'&&(a!=0)){				//统计'P'之后'T'的个数 
				++b;
			}
			if(str[i]=='T'&&(a==0)){				//如果'T'在'P'之前就返回false 
				return false;
			} 
		}else{	//含有别的字符,直接返回false 
			return false;
		}
	}
	
	if(a==1&&b==1){						//限制字符串仅含一个'P'和一个'T',且'P'在'T'之前 
		int c=0,d=0,e=0;				//辅助变量 
		for(int i=0;i<len;++i){			//重新统计abcde的值 
			if(str[i]=='P'){	 
				++a;
			}
			if(str[i]=='T'){
				++b;
			}
			if(str[i]=='A'&&a==1){			//c表示字符串中'P'之前'A'的个数
				++c;
			}
			if(str[i]=='A'&&a==2&&b==1){	//d表示字符串中'P'和'T'之间'A'的个数
				++d;
			}
			if(str[i]=='A'&&a==2&&b==2){	//e表示字符串中'T'之后'A'的个数
				++e;
			}
		}
		if((c==0&&e==0&&d!=0)||(c*d==e&&d!=0)){		//前半句表示只有'P'和'T'之间有'A'且必须有,后半句的d!=0用于排除字符串就是PT的情况 
			return true;
		}
	}
	return false;
}

int main(){
	int n=0;
	while(scanf("%d",&n)!=EOF){		//循环输入数字 
		string str[n];				//声明字符串数组 
		for(int i=0;i<n;++i){	
			cin>>str[i];			//这里使用标准库cin给字符串数组赋值 (这里有一个疑问,使用scanf函数怎么给字符串数组赋值) 
		}
		for(int i=0;i<n;++i){		//循环判断字符串数组中每个字符串是否正确 
			if(isRight(str[i])){	//调用判断函数 
				cout<<"YES"<<endl; 
			}else{
				cout<<"NO"<<endl;
			}
	}
	}
	return 0;
} 

码字不易,记得点赞哦~

  • 22
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

byg_qlh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值