【PAT】我要通过!

答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于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) 知,有 2 种基本情况是 “正确” 的,即 PAT 和 xPATx;
  • 由条件 (3) 知,其余 “正确” 情况都是由那 2 种基本情况不断演变而来。

因此我想到的是递归暴力法:

  • 首先判断 2 种基本情况为 “正确”。
  • 要想 aPbATca “正确”,就要 aPbTc “正确”,于是用 string.find() 找到 aPbATca 中 'P' 和 'AT' 的下标,通过 string.substr() 截取字符串获得 aPbTc,递归判断 aPbTc 是否 “正确”。
 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 bool onlyA(string s) {
 7     for (int i = 0; i < s.size(); i++)
 8         if (s[i] != 'A')
 9             return false;
10     return true;
11 }
12 
13 bool isCorrect(string s) {
14     if (s == "PAT")  return true;
15     else if (s.find("PAT") != string::npos) {
16         int idx = s.find("PAT");
17         string x1 = s.substr(0, idx), x2 = s.substr(idx + 3);
18         if (onlyA(x1) && onlyA(x2) && x1 == x2)
19             return true;
20     }
21     else if (s.find("P") != string::npos) {
22         int p_idx = s.find("P");
23         string a1 = s.substr(0, p_idx);
24         string a2 = s.substr(s.size() - p_idx);
25         if (onlyA(a1) && onlyA(a2) && a1 == a2 && s.find("AT") != string::npos) {
26             int at_idx = s.find("AT");
27             string b = s.substr(p_idx + 1, at_idx - p_idx - 1);
28             string ca = s.substr(at_idx + 2);
29             string c = ca.substr(0, ca.size() - a2.size());
30             if (isCorrect(a1 + "P" + b + "T" + c))
31                 return true;
32         }
33         else {
34             return false;
35         }
36     }
37     return false;
38 }
39 
40 int main() {
41     int n;
42     cin >> n;
43     string *s = new string[n];
44     for (int i = 0; i < n; i++)
45         cin >> s[i];
46     for (int i = 0; i < n; i++) {
47         if (isCorrect(s[i]))
48             cout << "YES" << endl;
49         else
50             cout << "NO" << endl;
51     }
52     return 0;
53 }

后来查看网上解析,总结题意发现:

  1. 基本情况是 xPATx,x 只含有 'A' 或为空。这里我们用 a、b、c 表示原题中相应位置  'A' 的数量,则初始情况下,a = c,b = 1。
  2. 由条件(3),'P' 和 'T' 中间每增加 1 个 'A',即 b + 1 后,整个字符串结尾要添加 1 个 'P' 前的字符串,即 c 变为 c + a。
    由初始状态 b = 1,且若 b = b + 1,则 c = c + a,可知 c = a × b

挖掘到这个深层信息,改写 isCorrect() 函数如下,效率会更高。

// C style
bool isCorrect(string s) {
    int a = 0, b = 0, c = 0;
    bool hasP = false, hasAT = false;
    for (int i = 0; i < s.size(); i++) {
        if (!hasP) {
            if (s[i] == 'A') {
                a++;
                continue;
            }
            else if (s[i] == 'P') {
                hasP = true;
                continue;
            }
            else {
                return false;
            }
        }
        else {
            if (!hasAT) {
                if (s[i] == 'A') {
                    b++;
                    continue;
                }
                else if (s[i] == 'T' && s[i - 1] == 'A') {
                    hasAT = true;
                    continue;
                }
                else {
                    return false;
                }
            }
            else {
                if (s[i] == 'A') {
                    c++;
                    continue;
                }
                else {
                    return false;
                }
            }
        }
    }
    if (hasP && hasAT && a * b == c)
        return true;
    else
        return false;
}

// C++ style
bool isCorrect(string s) {
    int idxP = s.find("P"), idxAT = s.find("AT");
    if (idxP != string::npos && idxAT != string::npos) {
        for (int i = 0; i < idxP; i++) {
            if (s[i] != 'A')
                return false;
        }
        for (int i = idxP + 1; i < idxAT; i++) {
            if (s[i] != 'A')
                return false;
        }
        for (int i = idxAT + 2; i < s.size(); i++) {
            if (s[i] != 'A')
                return false;
        }
        // a * b == c
        if (idxP * (idxAT - idxP) == (s.size() - idxAT - 2))
            return true;
    }
    return false;
}
原文地址:https://www.cnblogs.com/wayne793377164/p/8806902.html