Nothing that is worth knowing can be taught

1003 我要通过!(20)(20 分)

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

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

  1. 字符串中必须仅有P, A, T这三种字符,不可以包含其它字符;
  2. 任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字母 A 组成的字符串;
  3. 如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a, b, c 均或者是空字符串,或者是仅由字母 A 组成的字符串。

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

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

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

输入样例:

8
PAT
PAAT
AAPATAA
AAPAATAAAA
xPATx
PT
Whatever
APAAATAA

输出样例:

YES
YES
YES
YES
NO
NO
NO
NO

分析: 关于上面正确字符串的定义, 这是典型的递归定义, 第1点和第2点是初始条件, 第3点是归纳条件. 来说下显然可以得到的结论,
正确字符串必定有且只有一个P和一个T, 其余的都是A, 并且P在T的前面, 更具体地, 正确字符串必定是A...APA...ATA...A的模式.
仔细观察第3点, aPbATca和aPbTc的区别在于前者的P和T之前多了个A, T之后多了a, 可以想象, 面对一个给定字符串, 先要数出P之前有多少个A,
P和T之间有多少个A, T之后有多少个A, 首先判断是否符合第2点, 不符合就在T之后去掉与
P之前相同数量的A, 在P和T之间去掉一个A,
然后再判断剩下来的字符串是否为正确字符串, 重复若干次去掉的操作, 最后肯定归结到是否符合第2点. 但是有更好的办法,
既然每次都是去掉一个中间A和一个尾部a, 想象最后得到的aPATa形式, 将P前面A的数量设为x, P和T之间A的数量设为1, 那么每增加一个中间A就增加一个尾部a,
假设增加y次得到给定的字符串. 对于给定的字符串, P前面A的数量仍为x, P和T之间A的数量变为1+y, T之后A的数量变为x+xy=x(1+y), 那么给了一个字符串,
判断 中间A的数量 是否大于0而且 T之后A的数量 是否等于 P前A的数量 乘以 P和T之间A的数量 就可以了.

接着上代码:
#include <cstdio>
#include <cstdlib>
#include <string>
#include <iostream>
using namespace std;

const string rightAnswer = "YES";
const string wrongAnswer = "NO";

bool isRight(string s)
{
	// count len_front_A_string
	size_t index_of_A = 0; 
	while(index_of_A<s.length() && 'A' == s[index_of_A]) index_of_A++;
	if(index_of_A==s.length() || 'P' != s[index_of_A]) return false;
	size_t len_front_A_string=index_of_A;
	// count len_middle_A_string
	index_of_A++;
	size_t len_middle_A_string = 0;
	while(index_of_A<s.length() && 'A'==s[index_of_A]) 
	{
		index_of_A++;
		len_middle_A_string++;
	}
	if(index_of_A==s.length() || 'T' != s[index_of_A]) return false;
	// count len_back_A_string
	index_of_A++;
	size_t len_back_A_string = 0;
	while(index_of_A<s.length() && 'A'==s[index_of_A]) 
	{
		index_of_A++;
		len_back_A_string++;
	}
	if(index_of_A!=s.length()) return false;
	// 
	if(len_middle_A_string>0 && len_front_A_string*len_middle_A_string==len_back_A_string)
	{
		return true;
	}else
	{
		return false;
	}
}


int main()
{
	//freopen("input.txt", "r", stdin);
	int n;
	cin>>n;
	string inputStr;
	for(int i=0;i<n;i++)
	{
		cin>>inputStr;
		if(isRight(inputStr))
		{
			cout<<rightAnswer<<endl;
		}else
		{
			cout<<wrongAnswer<<endl;
		}
	}
	
	return 0;
} 

  

 




posted on 2018-07-21 18:58  Luxuer  阅读(1283)  评论(0编辑  收藏  举报

导航