1003 我要通过!(20)(20 分)
“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于PAT的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。
得到“答案正确”的条件是:
- 字符串中必须仅有P, A, T这三种字符,不可以包含其它字符;
- 任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字母 A 组成的字符串;
- 如果 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; }