“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于PAT的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。
得到“答案正确”的条件是:
1. 字符串中必须仅有P, A, T这三种字符,不可以包含其它字符;
2. 任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字母 A 组成的字符串;
3. 如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a, b, c 均或者是空字符串,或者是仅由字母 A 组成的字符串。
输入格式: 每个测试输入包含1个测试用例。第1行给出一个自然数n (<10),是需要检测的字符串个数。接下来每个字符串占一行,字符串长度不超过100,且不包含空格。
输出格式:每个字符串的检测结果占一行,如果该字符串可以获得“答案正确”,则输出YES,否则输出NO。
输入样例:8 PAT PAAT AAPATAA AAPAATAAAA xPATx PT Whatever APAAATAA输出样例:
YES YES YES YES NO NO NO NO
题目解析:
第一遍看题目把空字符串理解为空格了。。走了很多的弯路,最后才理解到只含有PAT三个字符串,那么问题就简化很多了。
首先最基本的形式为xxPATxx,PAT前后一定保证A的数量是一样的,如果没有A那就是“PAT"即为最简单的形式;
那么再看第三种,aPbATca这种形式若要成立的话,那么最后递归的结果一定是中间只有一个A,P前面的A数量与T后面的A数量一致,那么我们就可以归纳出P前面的A数量a与PT中间的A数量b还有与T后面的A数量ac的关系为:a*b=ac;
到这里我们发现所有的三种条件都满足这个关系式,因此我们可以按照这个方法敲出如下C++代码:
PS:其实这道题目的测试案例挺不严谨的,既没有判断P和T的位置关系,也没有判断P和T的数量问题,默认就是P在T前,而且只有一个PT...
#include <iostream> #include <string> using namespace std; bool pass(string s) { int flagp, flagt; int countp = 0, countt = 0;//P的位置,T的位置 int len; //字符串的长度 len = s.size(); for (int j = 0; j < len; j++) { switch (s[j]) { case'A': break; case'P': flagp = j; break; case'T': flagt = j; break; default: return false; } } if (((flagp - 0)*(flagt - flagp - 1) != (len - 1 - flagt)) ||((flagt - flagp) == 1))//上文推断的判断公式,如果中间没有A也是错的,所以要用flagt-flagp; return false; else return true; } int main() { int n; cin >> n; string *s = new string[n]; for (int i = 0; i < n; i++) { cin >> s[i]; } for (int i = 0; i < n; i++) { if (pass(s[i])) cout << "YES" << endl; else cout << "NO" << endl; } return 0; }
如果你推不出来上面那个判断公式的话,我这有一个特别笨的方法...为了纪念弯路还是贴上来吧
#include <iostream> #include <string> using namespace std; bool pass(string s) { int flagp, flagt; int countp=0,countt=0;//P的位置,T的位置 int len;//字符串的长度 len = s.size(); for (int j = 0; j < len; j++) { switch (s[j]) { case'A': break; case'P': flagp = j; countp++; if (countp>1) return false; break; case'T': flagt = j; countt++; if (countt > 1) return false; break; default: return false; } } if (((flagt - flagp) == 1)||(flagp>flagt)) return false;//确定PT位置是否合理 if (flagp != 0)//pat前面有字符 { for (int j = 0; j < flagp; j++) { if (s[j] != s[0]) return false; } for (int k = flagt + 1; k < len; k++) { if (s[k] != s[0]) return false; } } for (int j = flagp + 1; j < flagt; j++)//判断pat中间部分 { if (s[j] != 'A') return false; } string tmp; while(flagt - flagp >= 3)//中间超过两个A { tmp = ""; for (int j = 0; j < flagt-1; j++)//字符串前面不动,中间A减少一个 tmp = tmp + s[j]; tmp = tmp + 'T'; for (int j = 0; j < (len - flagt - 1-flagp); j++)//len-flag-1是c+a的长度,再减去flagp的长度就只剩下c的长度了 tmp = tmp + 'A'; flagt--; len = tmp.size(); } if (flagp == (len - flagt - 1)) return true; else return false; } int main() { int n; cin >> n; string *s=new string[n]; for (int i = 0; i < n; i++) { cin >> s[i]; } for (int i = 0; i < n; i++) { if (pass(s[i])) cout << "YES" << endl; else cout << "NO" << endl; } return 0; }