板栗说算法 之 PAT 乙级 1003 我要通过!(全方面解析)

 

一、题目

答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于 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.字符串中必须仅有 P、 A、 T这三种字符,不可以包含其它字符;

//入门条件是要有P和T,如果没有就直接no
if(name.find('P') != string::npos && name.find('T') != string::npos)
{
}else{
    cout << "NO" << endl;
}

2.寻找规律

PAT
PAAT
AAPATAA
AAPAATAAAA

//都是正确的

我们已经将P和T的条件准备完成了,最后剩下最为关键的A了

我们可以将aPbTc分为三块,1.P前面的 2.P到T的 3.T后面的,分别计数

之后会发现PAT的构造

1(P前面的有几个数):0 

2(P到T有几个数):1

3(T后面的有几个数):0

 

PAAT

1(P前面的有几个数):0 

2(P到T有几个数):2

3(T后面的有几个数):0

 

AAPATAA

1(P前面的有几个数):2

2(P到T有几个数):1

3(T后面的有几个数):2

 

AAPAATAAAA

1(P前面的有几个数):2

2(P到T有几个数):2

3(T后几个数):4

随后计算规律可得:(P前面的有几个数)* (P到T有几个数) = (T后几个数);

找到规律就好办了

分别计数之后进行判断是否(P前面的有几个数)* (P到T有几个数) = (T后几个数);

即可。

3.最后判断是否都为'A'

这里使用count(),C++标准模板库函数,用于统计某一值在一定范围内出现的次数。

 

头文件:#include <algorithm>

if(count(name.begin(),name.end(),'A') != name.size() - 2)
{
   temp = 0;
};

4.解决BUG

下代码完成后我使用案例PT,输出为正确,这显然是不对的。

PT

P前面的数有0个;

P到T的数有0个;

T后面的数有0个;

这在我们的判断中是对的

(P前面的有几个数)* (P到T有几个数) = (T后几个数);

0*0=0;

但是这不符合字符串中必须仅有 P、 A、 T这三种字符的标准。

所以我将P到T之间如果有0个的话输出为“NO”;

 //num_3为P到T之间有几个
 if(num_3 == 0)
{
   cout << "NO" << endl;
}

三、代码实现

#include <iostream>
using namespace std;

#include <string>

//ccount头文件
#include <algorithm>
int main()
{
    //用户输入
    int num;
    cin >> num;
    
    //循环输入进行判断
    for(int i = 0; i < num; i++)
    {
        //读取输u入
        string name;
        cin >> name;
        
        //如果字符串中没有P和T则NO
        if(name.find('P') != string::npos && name.find('T') != string::npos)
        {
            //用于判断的临时变量,默认为真
            int temp = 1;
            
            //记录‘P’前面的个数
            int num_1 = name.find('P');
            
            //记录‘T’后面的s个数
            int num_2 = name.size() - name.find('T') -1;
            
            //记录'P'到'T'之间的个数
            int num_3 = name.find('T') - num_1 - 1;

            //如果'P'到'T'之间的个数为0的话输出NO
            if(num_3 == 0)
            {
                cout << "NO" << endl;
            }
            
            //如果u符合规律的话进入下一步f判断
            else if(num_1 * num_3 == num_2)
            {
                //判断除了'P'和'T'之外的字母是否为’A‘,不为A则temp=0
                if(count(name.begin(),name.end(),'A') != name.size() - 2)
                {
                    temp = 0;
                };
                
                //最后判断该字符串是否是所需要的
                if(temp == 1)
                {
                    cout << "YES" << endl;
                }else{
                    cout << "NO" << endl;
                }
            }else{
                //如果不符合规律就输出NO
                cout << "NO" << endl;
            }
        }else{
            //如果没有P和T就输出NO
            cout << "NO" << endl;
        }
    }
}

如果有所帮助的话,记得点个关注哟,每天更新博客,一同进步!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章