1003 我要通过! (20 point(s))

// 15point 乱来写乱来凑输出
// 虽然能够通过样例,但实际连题目给出的条件都没有全覆盖 
#include <bits/stdc++.h>
using namespace std;

int main() {
	int n;
	cin >> n;
	
	while(n--){
		string str;
		cin >> str;
		
		// 定义标记 
		int flag = 0, a = 0; 
		for(auto s: str){
			
			if(s == 'P') flag = 1;
			else if(flag == 1 && s == 'A') flag = 2;
			else if(flag == 2 && s == 'T') flag = 3;
			
			// 当flag开始计数 但不为条件字符 
			else if(flag > 0 && s != 'A' && s != ' '){
				flag = 0;
			}
			
			// 记录中间出现A的次数 
			if(flag > 0 && s == 'A') a++;
			// 重置A出现次数 
			else  a = 0; 
			
			if(flag == 2 && a >= 3) flag = 0;
			
			if(2 < a && a < 4 && flag == 3){
				break;
			}  
		}
		
		// 如果标记没被重置 并且 == 3
		if(flag == 3)cout << "YES" << endl;
		else cout << "NO" << endl;
	}
}
// 全AC
#include <bits/stdc++.h>
using namespace std;

int main() {
	int n;
	cin >> n;
	while(n--){
		string str;
		cin >> str;
		// 标记前中后A个数 标记位置 
		int A[3]{0}, flag = 0;
		for(auto s: str){
			// 任一非条件字符退出
			if(s != 'P'  && s != 'A' && s != 'T') break;
			else if(s == 'P') flag = 1;
			else if(s == 'T') flag = 2;
			else if(s == 'A') A[flag]++;
		}
		// 中间有一个A 且满足条件三公式YES 
		if(A[1] > 0 && flag == 2 && A[0] * A[1] == A[2])	cout << "YES" << endl;
		else cout << "NO" << endl;
	}
}

这题当时写得比较乱,后面脑子冷静了一点想到了当时的找规律和分析的方法,才勉勉强强凑出代码至少过了样例,但是里面有很多情况还是没有考虑清楚。因为最开始分析的时候就没按正确的思路走。虽然现在还是没怎么理解题目到底想表达什么。

看了别人的说明,原来条件三想表达的是 开头A个数 * 中间A个数 = 结尾A个数 这样一个规律。当时只是盯着小写的 a b c,不晓得什么意思,而且前面的空字符串也不知道想表达什么,还以为是空格什么东西。而且没看到一个细小的 “均” 的字眼,原来是可以将所有 a b c 看出 A 的,而且也没看到后面还有一个“字符串”,也就说不仅仅是可以看成 A 并且还可能是 AAAAA…… 。(看别人的说明还是没理解这个“空字符串”想表达什么,似乎样例也没这回事)。

而且当时没能够结合样例来理解这个意思,就算不知道空字符串,也得先当初 A 来理解至少过个样例再说。如果我们没有明白这个叼毛条件表达的意思,只知道给出了了一个, aPbTc 或 aPbATca 什么乱七八糟的东西。那么再看到样例。先来数一数找找有什么规律能够凑上去。

固定 P T 不管的话,只盯着前中后的 A。

YES:
PAT 0 1 0
PAAT 0 2 0
AAPATAA 2 1 2
AAPAATAAAA 2 2 4

NO:
APAAATAA 1 3 2

这样数一数,第一个前面有一个 0 所以乘中间的后面也是一个 0,第二个同理。而后面两个也是很直观地能够看出相乘关系。再看类似的错误的例子,1 * 3 != 2,所以就错误了。这样就能够稍微理解下这题目到底想说什么了(所以以后不会的时候记得找规律,标记数字,也许有点鸟用)。

liuchuo参考代码

博客园参考代码


又多参考了其他几位的思路,感觉比柳诺的说明要详细一点,结合题目进一步说明,视野要开阔一点。

而看到别人的讲解之后,让自己反思当时对于条件的认识是有一定的偏差的,或者说没有能够以一种明确的关系看出条件之间的联系。到底是一种平行的独立的,还是互相影响,相互推导的关系。显然这题目就是后者,从条件一可以不断深入推到条件三。

  1. 字符串中必须仅有P, A, T这三种字符,不可以包含其它字符;

先从条件一出发,并实现条件的话,字符串首先需要仅有这几个字符组成。以为着任一非条件字符的时候判断就可以结束了。那么在判断过程中可以给出下面的代码

if(s != 'P' && s != 'A' && s != 'T') break;

  1. 任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字母 A 组成的字符串;

由条件一基础进一步明确条件二,前面说需要 P A T 三个字符,那么条件二除了满足这三个字符以外,还需要满足 PAT 三个字符组成这样连续的顺序。并且还附带了 x 。

x 这个空字符串目前我仍然无法理解,但是这里给出两个条件除了空之外,还有就是 A 组成的字符串。所以虽然另一个看不出来,但至少要对能够看懂的先实现。也就说把 x 当初 A 甚至 A 组成的字符串的话,就有 APATA 或者 APATAAAAAA……

在这样理解下,我们首先需要满足 PAT 的这三个字符组成的顺序,再者在这个格式两旁,需要仅由 A 组成的字符串。

关于 PTA 字符的判断在前面已经给出,所以 x 是错误字符的可能不必再考虑。而关于顺序问题,我们先用一个变量标记,遇到 P 就变为 1 遇到 T 就变成 2 并且根据格式, PAT 中间目前只有一个 A 字符,而刚才标记 P T 的时候,刚好可以根据 P = 1 的情况,来判断当前是 P T 的中间,然后用一个数组来统计中间的 A 的个数。

if(s == 'P') flag = 1;
if(s == 'T') flag = 2;

if(s == 'A') A[flag]++;

最后在判断的时候,结合上面的,要满足 PAT 三个字符出现,并且中间有一个A,可以先满足第二个条件的要求。

if(A[1] == 1 && flag == 2)

  1. 如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a, b, c 均或者是空字符串,或者是仅由字母 A 组成的字符串。

条件三的公式上面已经给出,同样是沿着条件二的思路进一步拓展,从了满足前后具有 A 字符串情况外,同时 A 字符串仍需要满足 头A个数 * 中间A个数 = 结尾A个数 的关系。所以刚才的 A 数组 就派上用场,可以用来对前中后的 A 的计数。

对代码稍加更改,首先中间的 A 不一定只有一个,再者判断需要满足公式的条件。总结判断语句有。

if(A[1] > 0 && flag == 2 && A[0] * A[1] == A[2])

这样就可以全 AC 这个题目。

CSDN参考代码

知乎专栏参考代码


当然当上面的分析为止就可以全AC,但是并没有覆盖很多参考里面提到的条件,比如很多里面提到的 P T 仅有一个字符,但是可以看到这里并没有这个判断就AC了。

这到底是参考里面多此一举,还是题目尚不够完善,目前就不得而知了。总之通过这题的分析的方法还是应该学到的。

结合条件和样例对变量进行标记;对不同的条件先化简以最少的情况进行考虑,再逐渐增加条件;考虑条件之间到底是平行还是递进关系等等。


还有当时看到 a b c 三个字母还以为是不同的变量,但结合参考文章里面提到的, 并且题目也有说明 “a、 b、 c 均或者是空字符串,或者是仅由字母 A 组成的字符串” 这个字眼很关键,实际上把 a b c 看出 x 同一个变量也是没有问题,或者单纯是 A 也是可以的。所以读题上也很关键,要注意这些关键的字眼。

实在不会就破罐子破摔,先往统一的看待!管他三七二十一,反正样例里面通过的也是这样表示的。

posted on 2021-09-05 17:21  Atl212  阅读(52)  评论(0)    收藏  举报

导航