“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于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;
}