1003 我要通过!(20)

发表在专栏“PAT乙级题目详解”,并在持续更新中。

https://blog.csdn.net/column/details/23947.html


答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于PAT的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。

得到“答案正确”的条件是:

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

  1. 任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字母 A 组成的字符串;\
  2. 如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a, b, c 均或者是空字符串,或者是仅由字母 A 组成的字符串。

现在就请你为PAT写一个自动裁判程序,判定哪些字符串是可以获得“答案正确”的。

输入格式: 每个测试输入包含1个测试用例。第1行给出一个自然数n (<10),是需要检测的字符串个数。接下来每个字符串占一行,字符串长度不超过100,且不包含空格。

输出格式:每个字符串的检测结果占一行,如果该字符串可以获得“答案正确”,则输出YES,否则输出NO。

分析:

看到这个题目,首先是从“A”“P”“T”的位置和数量分析,

1.假设left表示“P”的数量,显然“P”的数量有且只有一个;P的前面应该是没有或者仅有“A”;

2.mid表示中间的“A”的数量,mid的数量也要大于等于1;

3.right表示“T”的数量,right的数量应该为1.right的前面是“P”和“A”,并且“P”和“T”之间至少有一个“A”(即mid == 1)。

#include 
#include 
using namespace std;

int main()
{
	int n;
	cin >> n;
	string test;
	int l = 0;//输入的字符串的长度

	for (int i = 0; i < n; i++)
	{
		int left = 0;//记录左边的"P"出现的次数
		int mid = 0;//记录中间的"A"出现的次数
		int right = 0;//记录右边的"T"出现的次数
		//输入一个字符串,判断
		cin >> test;
		l = test.size();
		//遍历字符串中的每一个字母
		for (int j = 0; j < l; j++)
		{
			////如果出现了非法字符,直接输出“NO”,并结束
			if (test[j] != 'P' && test[j] != 'A' && test[j] != 'T' && test[j] != ' ')
			{
				//cout << "NO" << endl;
				break;
			}
			//如果当前字符是"A",则继续循环,知道找到"P"
			if (test[j] == 'A')
			{
				if (left == 1)
				{
					mid++;
				}
				continue;
			}
			//如果当前字符是"P",
			if (test[j] == 'P')
			{
				left++;
				continue;
			}
			//如果当前字符是"T"
			if (test[j] == 'T')
			{
				if (mid >= 1)
				{
					right++;
				}
				continue;
			}

		}
		if (left == 1 && right == 1 && mid >= 1)
		{
			cout << "YES" << endl;
		}
		else
		{
			cout << "NO" << endl;
		}
	}
	system("pause");
	return 0;
}

这种思路只能通过前面的7个测试,“APAAATAA”这种情况不通过。

仔细想一下,应该“如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a, b, c 均或者是空字符串,或者是仅由字母 A 组成的字符串。”这句话的问题。

(1)这句话说的是任意满足条件的aPbTc正确,则可以得到另外一个正确的表达式aPbATca。

(2)那么最简单的正确的表达式是PAT(b的初始值是A),可以得到PAAT也是正确的,延伸出PAAAT正确。

(3)在第(2)条是在“a”和“c”为空的情况下得到的,那么在“a”“c”赋值的情况下,假设“a” “c”都为“A”,那么“APATA”是正确的,可以得到“APAATAA”也是正确的,延伸出“APAAATAAA”也是正确的,到这,是不是发现了一些规律呢?还没有发现吗,好吧,再来看

(4)“a”赋值“A”c赋值“AA”(这样设置的原因是在第(3)条中“a”和“c”设置的是一样的,所以在本条中希望设置的不一样,以体现规律的适用性),最简单的是“APAATAA”,可以得到“APAAATAAA”.可能有人会疑问为什么在“a”赋值“A”c赋值“AA”的情况下,最简单的不是“APATAA”呢?因为如果把它写成“aPbATca”形式,找不到一个“aPbTc”形式来验证它的正确性。

(5)得出结论,每一次的延伸,b都是多了一个“A”,同时“ca”也是“a”的翻倍,所以可以得到结论a*b = c,符合这个条件的就是对的,不符合就是错的。

(6)原来这个题目看起来这么难,分析到最后,仅仅是一个找规律的题目而已啊。生活中有很多看似很难的事情,多尝试一下,同样可以成功的!!!

好了,不多说了,附代码:

#include 
#include 
using namespace std;

int main()
{
	int n;
	cin >> n;
	string test;
	int l = 0;//输入的字符串的长度

	for (int i = 0; i < n; i++)
	{
		int left = 0;//记录左边的"A"出现的次数
		int mid = 0;//记录中间的"A"出现的次数
		int right = 0;//记录右边的"A"出现的次数
		int t = 0;//记录T出现的次数
		int p = 0;//记录P出现的次数
		//输入一个字符串,判断
		cin >> test;
		l = test.size();
		//遍历字符串中的每一个字母
		for (int i = 0; i < l; i++)
		{
			////如果出现了非法字符,结束
			//if (test[j] != 'P' && test[j] != 'A' && test[j] != 'T' && test[j] != ' ')
			//{
			//	//cout << "NO" << endl;
			//	break;
			//}
			//计算"P"之前的"A"的数目,之前一定要没有出现过"P"
			if (test[i] == 'A' && p == 0 && t == 0)
			{
				left++;
				continue;
			}
			//计算"P"的数目,
			if (test[i] == 'P')
			{
				p++;
				continue;
			}
			//计算中间的"A"的数目,之前一定要出现一个"P",并且只能出现这一个
			if (test[i] == 'A' && p == 1 && t == 0)
			{
				mid++;
				continue;
			}
			//计算"T"的数目,"T"之前必定要出现"A"
			if (test[i] == 'T' && mid >= 1)
			{
				t++;
				continue;
			}
			//计算后面的"A"的数目,之前一定要出现一个"T"
			if (test[i] == 'A' && p == 1 && t == 1)
			{
				right++;
				continue;
			}
			else
			{
				break;
			}

		}
		//结束并判断
		//
		if (p == 1 && t == 1 && left * mid == right)
		{
			cout << "YES" << endl;
		}
		else
		{
			cout << "NO" << endl;
		}
	}
	system("pause");
	return 0;
}

你可能感兴趣的:(PAT,(Basic,Level),Practice,(中文,PAT乙级题目详解)