PAT乙级1003我要通过的做题笔记

分析题意

得到"答案正确"的条件是:

字符串中必须仅有 P、 A、 T这三种字符,不可以包含其它字符;

任意形如 xPATx 的字符串都可以获得"答案正确",其中 x 或者是空字符串,或者是仅由字母 A 组成的字符串;

如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a、 b、 c 均或者是空字符串,或者是仅由字母 A 组成的字符串。

根据题目中的规则,如果aPbTc是正确的,那么aPbATca也是正确的。这里我们可以把字符串中P之前的A的个数看作x,P和T之间的A的个数看作y,T之后的A的个数看作z。

对于初始的合法字符串xPATx,这里x可以为空字符串或者仅由A组成的字符串,此时有x个A在P之前,1个A在P和T之间,x个A在T之后,满足x * 1=x的关系。

当按照规则扩展时,比如从aPbTc变为aPbATca,如果P之前A的个数为a,P和T之间A的个数从b变为b + 1,T之后A的个数从c变为c + a。这种变化始终保持着a * b=c的关系(在原始的xPATx中就是x * 1=x)。

总之就是:只有P,A,T三种字符,PT之间必须有A,P前面的A * PT之间的A == T之后的A

代码思路

确定字符种类

要检测只有三种字符,还有统计其中A,P,T的个数,可以想到利用键值对map,分别检测字符和字符数量,那么就创建一个map<char ,int>类型的键值对变量m。

我们就可以通过遍历字符串的每个字符的方式,来确定字符种类数,和每种字符的个数。

确定A的数量关系

要确定A的数量关系,可以利用下标(索引)来求,我们可以发现字符串索引从0开始,那么P之前A的个数就可以用P的下标来代表,那么我们在循环中一旦遍历到'P',我们就把它的下标存到一个变量p中作为P前面A的个数。

PT之间

T的索引 - P的索引再减去1.比如

PTA

012

2 - 0 - 1 = 1,1为PT间A的个数

T之后A的个数

字符串长度 - T的索引 - 1

PTAAAA

0123456

6 - 1 - 1 = 4为T之后A的个数

P和T之间必须有A

那么P和T的索引之差就不能小于1

只有P,A,T三种字符

那么m.size() == 3,如果还有多的或者是不足三种,m.size()就不为3了

m.size()代表的是这个键值对中字符种类的个数

P,T个数只有一个

那么,m['P'] == 1, m['T'] == 1

代码实现

cpp 复制代码
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
    string s;
    int n = 0;
    int t = 0;
    int p = 0;
    cin >> n;
    int i = 0;
    for (i = 0; i < n; i++)
    {
        cin >> s;
        map <char, int> m;

        int j = 0;
        for (j = 0; j < s.size(); j++)
        {
            m[s[j]]++;//统计字符种类数,以及每种字符的个数
            if (s[j] == 'P')
            {
                p = j;
            }
            if (s[j] == 'T')
            {
                t = j;
            }
        }
        if (m['T'] == 1 && //T只有一个
            m['P'] == 1 && //P只有一个
            m.size() == 3&& //只有P,A,T三种字符
            t - p > 1 && //P和T之间必须有A
            m['A'] != 0 &&//A的个数不为0
            p * (t - p - 1) == s.length() - t - 1//P前的A * PT间的A == T后的A
            )
        {
            cout << "YES" << endl;
        }
        else
        {
            cout << "NO" << endl;
        }
    }
    return 0;
}

自己写的错误

将if (s[j] == 'P')写成if (m[s[j]]=='P')

分析

  1. 原意
    • 当代码为if (s[j]=='P') p = j;时,它的原意是检查字符串s中的第j个字符是否为'P'。如果是,就将j的值赋给变量p,这里p很可能是用来记录字符'P'在字符串中的位置索引。
  2. 错误写法的影响及区别
    • 当写成if (m[s[j]]=='P') p = j;时:
      • 首先,m是一个map<char, int>类型,m[s[j]]会返回一个int类型的值(这个值是字符s[j]m中的计数)。而'P'是一个字符常量。在C++ 中,将一个int类型的值与一个字符常量进行比较是类型不匹配的操作。
      • 这种错误写法会导致程序逻辑混乱。因为它不是在检查字符串中的字符是否为'P',而是在检查字符s[j]m中的计数是否等于字符'P'的ASCII码值(实际上由于类型不匹配,这种比较没有实际意义)。这与原代码的功能完全不同,原代码是在寻找字符串中'P'字符的位置,而错误写法是在对一个不相关的计数进行无意义的比较。

map<char, int> m不放入循环

分析

  1. 作用域与数据复用问题
    • 如果将map<char, int> m;放在循环外面,每次循环不会重新创建一个新的m
    • 这可能导致数据复用问题。例如,在处理多个不同的输入字符串时,m会累积之前字符串中字符的计数信息。如果第一个字符串是"PAT",处理完后m['P'] = 1m['A'] = 1m['T'] = 1。当处理下一个字符串时,m已经有了之前的计数,这会干扰对新字符串中字符的正确统计。
  2. 逻辑错误
    • 从逻辑上讲,程序可能会得到错误的结果。因为对于每个输入字符串,都应该独立地统计其中字符的出现次数。如果m在循环外,就无法保证每个字符串的统计是独立的。例如,程序可能会错误地判断字符出现的次数或者满足某些条件的情况,如判断是否只有特定的字符(PAT)以及它们的数量关系是否符合要求等都会因为m的复用而得出错误的结论。

漏写m[s[j]]++;

  1. 代码目的

    • 在这段代码中,m[s[j]]++;这行代码的目的是统计字符串中每个字符出现的次数。
    • 这里m是一个map<char, int>类型的容器,它的键是字符类型(char),值是整数类型(int)。
    • 当执行m[s[j]]++;时:
      • 如果s[j]这个字符是第一次出现在字符串中,那么m[s[j]]会创建一个新的键值对,键为s[j],值初始化为0,然后执行++操作后,这个字符对应的计数就变为1,表示这个字符出现了1次。
      • 如果s[j]这个字符已经在之前出现过,那么m[s[j]]会直接找到对应的键值对,然后执行++操作,将这个字符的计数加1,表示这个字符又出现了一次。
    • 这样做是为了后续判断字符串中是否只有PAT三种字符(通过m.size()==3判断)以及判断PAT的数量是否符合要求(例如m['P'] == 1等)。
  2. 计数功能缺失

    • 如果没有m[s[j]]++;这行代码,首先会导致字符计数功能无法实现。
    • 假设m是用于统计字符串中字符出现次数的map,原本这行代码会根据字符串中的字符s[j],在m中找到对应的键(如果不存在则创建),并将其对应的值加1。没有这行代码,就不能对字符串中的字符进行计数。
  3. 后续判断错误

    • 在程序后续可能存在对字符出现次数的判断逻辑。例如,可能需要判断某个字符是否只出现了特定的次数,或者判断不同字符出现次数之间的关系。
    • 由于没有正确统计字符出现次数,这些判断都会得出错误的结果。例如,如果需要判断字符串中是否只有特定的三种字符(如PAT)且数量关系符合某种规则,由于没有准确的计数,可能会错误地认为字符串满足或不满足条件。

代码引用

柳婼的代码

相关推荐
Lbs_gemini060321 分钟前
C++研发笔记14——C语言程序设计初阶学习笔记12
c语言·开发语言·c++·笔记·学习
MC何失眠1 小时前
vulnhub靶场【哈利波特】三部曲之Fawkes
网络·python·学习·网络安全
MarisolHu1 小时前
前端学习笔记-Vue篇-02
前端·vue.js·笔记·学习
叁散1 小时前
PTA--数据结构预习报告: 考试排名汇总
数据结构
霖大侠2 小时前
Adversarial Learning forSemi-Supervised Semantic Segmentation
人工智能·算法·机器学习
阿华的代码王国3 小时前
【算法】——前缀和(矩阵区域和详解,文末附)
java·开发语言·算法·前缀和
Sunyanhui13 小时前
力扣 LCR训练计划2(剑指 Offer 22. 链表中倒数第k个节点)-140
算法·leetcode·链表
yours_Gabriel3 小时前
【力扣】3274. 检查棋盘方格颜色是否相同
算法·leetcode
Chandler243 小时前
蓝桥杯经验分享
经验分享·算法·蓝桥杯
我的老子姓彭3 小时前
C++学习笔记
c++·笔记·学习