题目及要求
“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于 PAT 的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。
得到“答案正确”的条件是:
字符串中必须仅有 P、 A、 T这三种字符,不可以包含其它字符;
任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字母 A 组成的字符串;
如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a、 b、 c 均或者是空字符串,或者是仅由字母 A 组成的字符串。
现在就请你为 PAT 写一个自动裁判程序,判定哪些字符串是可以获得“答案正确”的。
输入格式:
每个测试输入包含 1 个测试用例。第 1 行给出一个正整数 n (≤10),是需要检测的字符串个数。接下来每个字符串占一行,字符串长度不超过 100,且不包含空格。
输出格式:
每个字符串的检测结果占一行,如果该字符串可以获得“答案正确”,则输出 YES,否则输出 NO。
输入样例:
10
PAT
PAAT
AAPATAA
AAPAATAAAA
xPATx
PT
Whatever
APAAATAA
APT
APATTAA
输出样例:
YES
YES
YES
YES
NO
NO
NO
NO
NO
NO
前言
这个题目的描述有一点不太清楚,需要多读几遍题目,在这里有三个条件,前面两个条件比较好理解一点,主要在于最后一个
1:P A T 三个字母必须都有,且只有这三个字母 且 P T 只能出现一次
2: P 和 T 之间必须至少有一个A
最后一个需要去找一下规律,aPATa的基础上 中间每多一个A 后面就要多出一个前面的a
例如:APATA,P前面(前段)和中间分别有一个A,那么11=1 即前段A的数量中段A的数量等于后段A的数量
APAATAA:前段有一个A,中段有两个A,则后段有也有两个A:也就是12=2
AAPAATAAAA:前段有两个A,中段有两个A,后段有四个A:也就是22=4
根据输入案例去进行找规律即可知道:前段部分*中段部分=后段部分
解题思路
在该程序中,我们首先定义了一个名为 is_correct 的函数,用于判断一个字符串是否符合题目要求。该函数接受一个字符串作为输入,并返回一个布尔值,表示该字符串是否符合要求。
在函数中,我们首先使用两个变量 count_p 和 count_t 来统计字符串中 P 和 T 的数量,并使用两个变量 pos_p 和 pos_t 来记录它们的位置。如果字符串中包含除 P、A、T 以外的其他字符,则直接返回 false。
接下来,我们判断字符串是否符合 xPATx 的形式,即 P 和 T 之间必须至少有一个 A。如果不符合,则返回 false。
最后,我们判断字符串是否符合 aPbATca 的形式,即字符串可以被分成三个部分,左边部分由若干个 A 组成,中间部分由一个 P 和若干个 A 组成,右边部分由若干个 A 和一个 T 组成,并且左边部分与中间部分的长度乘积等于右边部分的长度。如果不符合,则返回 false。
在主函数中,我们首先读入测试数据的数量 n,然后依次读入每个测试数据,并调用 is_correct 函数判断其是否符合要求。如果符合,则输出 YES,否则输出 NO。
#include <iostream>
#include <string>
using namespace std;
// 判断字符串是否符合要求的函数
bool is_correct(string s) {
int count_p = 0, count_t = 0; // 统计 P 和 T 的数量
int pos_p = -1, pos_t = -1; // 记录 P 和 T 的位置
for (int i = 0; i < s.length(); i++) { // 遍历字符串中的每个字符
if (s[i] == 'P') { // 如果当前字符是 P
count_p++; // P 的数量加一
pos_p = i; // 记录 P 的位置
} else if (s[i] == 'T') { // 如果当前字符是 T
count_t++; // T 的数量加一
pos_t = i; // 记录 T 的位置
} else if (s[i] != 'A') { // 如果当前字符不是 P、A、T 中的任何一个
return false; // 字符串不符合要求,返回 false
}
}
if (count_p != 1 || count_t != 1 || pos_t - pos_p <= 1) { // 如果 P 或 T 的数量不为 1,或者它们之间的距离小于等于 1
return false; // 字符串不符合要求,返回 false
}
int len_left = pos_p; // 计算前段部分的长度
int len_mid = pos_t - pos_p - 1; // 计算中段部分的长度
int len_right = s.length() - pos_t - 1; // 计算后段部分的长度
if (len_left * len_mid != len_right) { // 如果前段部分和中段分的长度乘积不等于后段部分的长度
return false; // 字符串不符合要求,返回 false
}
return true; // 字符串符合要求,返回 true
}
int main() {
int n;
cin >> n; // 读入测试数据的数量
for (int i = 0; i < n; i++) { // 循环读入每个测试数据
string s;
cin >> s; // 读入当前测试数据
if (is_correct(s)) { // 如果当前测试数据符合要求
cout << "YES" << endl; // 输出 YES
} else { // 如果当前测试数据不符合要求
cout << "NO" << endl; // 输出 NO
}
}
return 0;
}
总结
这个题目主要在于理解题目意思,其它都不是什么大问题,认真阅读即可。