1003 我要通过!

1003 我要通过! (20 分)

题目描述:

“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于 PAT 的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。

得到“答案正确”的条件是:

  1. 字符串中必须仅有 P、 A、 T这三种字符,不可以包含其它字符;
  2. 任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字母 A 组成的字符串;
  3. 如果 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’ 的数量。

这样,我们就可以进一步得到判定一个字符串是否合法的逻辑。

  1. 若字符串中含有‘P’‘A’‘T’之外的字符,非法。

  2. 若字符串中‘P’‘T’出现次数不等于1,非法。

  3. 若字符串中‘T’ 先于 ‘P’ 出现,非法。

  4. 若字符串中‘P’ ‘T’之间’A’的数量小于1,非法。

  5. 若字符串两端A的数量相等,合法。

  6. 若字符串两端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;
}

易错点:

  • 要找到三条规则之间的递进关系。
  • 第三条规则表达的数量关系。
  • 做题目最重要的是心平气和,不开心的时候最好不要做题目。
  • 别忘了关掉在本地调试的时候加上去的输入重定向代码。

总结:
Python-version
C++version
java-success
js

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值