zoukankan      html  css  js  c++  java
  • 【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;
    }
  • 相关阅读:
    left join问题
    SQL索引
    数据库查询优化
    define and inline
    程序的内存分配
    __closure
    this指针
    java笔记
    Visual Studio Code(VSCODE)语言设置
    Excel 2010如何打开多个独立窗口?
  • 原文地址:https://www.cnblogs.com/wayne793377164/p/8806902.html
Copyright © 2011-2022 走看看