1003 我要通过! (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’, ‘A’, ‘T’ 这三种字符。包含任何其他字符或者三者中有任意字符不存在的都是非法字符串。
第二条规则表示在一个“PAT”字符串的两端可以同时添加任意个‘A’。既然‘A’是同时添加上去的,那么根据第二条规则产生的字符串两端的‘A’的数量必然相等。
第三条规则是在第二条规则基础之上的。若aPbTc为合法字符串,则b一定是‘A’而不能是‘ ’(空格),因为‘PT’不能由规则1或者规则2产生,不是合法字符串。 第三题规则和第二条规则一样,在表达一种数量上的关系。即PT 之间每增加一个’A’,字符串的后端的’A’的数量就增加 前端的‘A’ 的数量 个。 也就是说,以第三种规则结束构造的字符串,P前面的‘A’ 的数量 * PT之间‘A’ 的数量 == T之后的‘A’ 的数量。
这样,我们就可以进一步得到判定一个字符串是否合法的逻辑。
-
若字符串中含有‘P’‘A’‘T’之外的字符,非法。
-
若字符串中‘P’‘T’出现次数不等于1,非法。
-
若字符串中‘T’ 先于 ‘P’ 出现,非法。
-
若字符串中‘P’ ‘T’之间’A’的数量小于1,非法。
-
若字符串两端A的数量相等,合法。
-
若字符串两端A的数量不等,且不满足 P前面的‘A’ 的数量 * PT之间‘A’ 的数量 == T之后的‘A’ 的数量, 非法。
代码:
- Python Version:
def main():
n = int(input())
#接收输入的整数
strings = []
for x in range(n):
strings.append(input())
#接收输入的字符串,用列表存储
for string in strings:
print(judge(string))
#依次判断每个字符串时候合法并输出
def judge(string):
p_count = 0
t_count = 0
# 计算‘P’ 和 ‘T’的数量
p_index = 0
t_index = 0
# 计算‘P’ 和‘T’的位置,并用位置计算对应的'A'的数量
answer = "YES"
#默认为合法字符串
for x in range(len(string)):
if string[x] != 'P' and string[x] != 'A' and string[x] != 'T':
# 判断依据 1
return 'NO'
if string[x] == 'P':
p_count += 1
p_index = x
if string[x] == 'T':
t_count += 1
t_index = x
if p_count != 1 or t_count != 1 or p_index > t_index:
# 判断依据 2, 3
return "NO"
if t_index - p_index - 1 == 0:
# 判断依据 4
return "NO"
# print("end ", (len(string) - 1 - t_index), " front ",
# p_index, " middle ", (t_index - p_index - 1))
if (len(string) - 1 - t_index) != p_index and (len(string) - 1 - t_index) != p_index * (t_index - p_index - 1):
# 判断依据 6
# len(string) - 1 - t_index, 'T' 后面的‘A’的数量
# p_index, ‘P’ 前面的‘A’ 的数量
# (t_index - p_index - 1), ‘P’ ‘T’ 之间 ‘A’ 的数量
return "NO"
return answer
if __name__ == '__main__':
main()
- C++ version:
#include <iostream>
#include <string>
using namespace std;
bool judge(string input_str);
int main(){
//freopen("in.txt","r",stdin);
int N = 0;
string input_str;
cin >> N;
for(int i=0; i<N; ++i){
cin >> input_str;
if(judge(input_str)){
cout << "YES" << endl;
}else{
cout << "NO" << endl;
}
}
return 0;
}
bool judge(string input_str){
int p_count = 0;
int t_count = 0;
int p_index = 0;
int t_index = 0;
for(int i=0; i<input_str.size(); i++){
if(input_str[i] != 'P' && input_str[i] != 'A' && input_str[i] != 'T'){
return false;
}else if(input_str[i] == 'P'){
p_count ++;
p_index = i;
}else if(input_str[i] == 'T'){
t_count ++;
t_index = i;
}
}
if(p_count != 1 || t_count != 1){
return false;
}
int a_between_pt = t_index - p_index - 1;
if(a_between_pt < 1){
return false;
}
if((input_str.size()-1-t_index != p_index) && (input_str.size()-1-t_index != p_index * a_between_pt)){
return false;
}
return true;
}
Java Version:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
for(int i=0; i<n; ++i) {
String input_str = in.next();
if(judge(input_str)) {
System.out.println("YES");
}else {
System.out.println("NO");
}
}
}
// 用java语言做题的时候,可以直接使用public static 的方法,便于调用。
public static boolean judge(String input_str) {
int p_count = 0, p_index = 0;
int t_count = 0, t_index = 0;
for(int i=0; i<input_str.length(); ++i) {
if(input_str.charAt(i) != 'P' && input_str.charAt(i) != 'A' && input_str.charAt(i) != 'T') {
// 字符串中只能有PAT三种字符
return false;
}else if(input_str.charAt(i) == 'P') {
p_index = i;
p_count ++;
}else if(input_str.charAt(i) == 'T') {
t_index = i;
t_count ++;
}
}
if(p_count != 1 || t_count != 1) {
// T和P的个数都都是有且只有一个
return false;
}
int a_between_pt = t_index - p_index - 1;
if(a_between_pt < 1) {
// 在仅有的两个PT之间至少有一个A
return false;
}
int front_a = p_index-1 - 0 + 1;
int end_a = input_str.length()-1 - (t_index + 1) + 1;
if(front_a != end_a && front_a * a_between_pt != end_a) {
return false;
}
return true;
}
}
- JavaScript ( Node.js) 版本:
var readline = require('readline');
var io = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
var line_counter = 0;
io.on('line', function(input_string){
if(line_counter != 0){
if(judge(input_string)){
console.log("YES");
}else{
console.log("NO");
}
}
line_counter +=1;
});
function judge(string){
var p_count = 0, p_index = 0;
var t_count = 0, t_index = 0;
for(var i=0; i<string.length; ++i){
if(string[i] != 'P' && string[i] != 'A' && string[i] != 'T'){
return false;
}else if(string[i] == 'P'){
p_index = i;
p_count ++;
}else if(string[i] == 'T'){
t_index = i;
t_count ++;
}
}
if(p_count != 1 || t_count != 1){
return false;
}
var a_between_pt = t_index - p_index - 1;
if(a_between_pt < 1){
return false;
}
var front_a_number = p_index - 1 - 0 + 1;
var end_a_number = string.length - 1 - (t_index + 1) + 1;
if(front_a_number != end_a_number && front_a_number * a_between_pt != end_a_number){
return false;
}
return true;
}
易错点:
- 要找到三条规则之间的递进关系。
- 第三条规则表达的数量关系。
- 做题目最重要的是心平气和,不开心的时候最好不要做题目。
- 别忘了关掉在本地调试的时候加上去的输入重定向代码。
总结: