1003

2020-04-21  本文已影响0人  古界族邪神
image.png
image.png
这道题让我想到了编译原理的内容,首先这道题的难点在于读懂第3个条件.这三个条件不是孤立的,是有联系的:
正确答案的字符串集合:条件2的字符串集合+条件3的字符串集合
条件3的字符串集合是由条件2的字符串集合扩充而来的

我们先分析条件2:
xPATx 注意前后两个x是一模一样的。
x只能包含A或者为空
那么条件2的字符串集合是中间有一个PAT,前后有数目一样的字母A(0个或者n个)

再分析条件3:
我一开始读条件3真是一头雾水。读了好几遍,看了一下解析才回过味来。
aPbTc:b中至少含有一个A,未扩充时a和c有同样数目的A
aPbATca:b中添加一个字母A,c中添加一个a

那么设a中有y个字母A,那么未扩充的c也有y个字母A;
PT之间有x个字母A,除了最开始的PAT中的一个A,后来添加了(x-1)个A,扩充了(x-1)次;
T之后又z个字母A。

z的字母A个数:(x-1) * y + y = z 也就是 x * y = z


示意图

PS:这道题让我学习到了一个挺有意思的函数:string类型的find_first_of()函数。它可以找到某个字符第一次出现的位置,返回下标。计算三个位置的A的数目很方便。

代码:

#include <iostream>
#include <vector>
using namespace std;

int main()
{
    int cou;
    cin>>cou;

    vector<string> strs;
    for(int i=0;i<cou;i++)
    {
        string str;
        cin>>str;
        strs.push_back(str);
    }

    for(int i=0;i<cou;i++)
    {
        string str=strs[i];
        bool flag=true;
        //条件一
        for(int j=0;j<str.length();j++)
        {
            if(str[j]!='P'&&str[j]!='A'&&str[j]!='T')
                flag=false;
        }

        //只有一个P
        int countP=0;
        for(int j=0;j<str.length();j++)
        {
            if(str[j]=='P')
                countP++;
        }
        if(countP!=1)
            flag=false;

        //只有一个T
        int countT=0;
        for(int j=0;j<str.length();j++)
        {
            if(str[j]=='T')
                countT++;
        }
        if(countT!=1)
            flag=false;

        //P在T之前
        if(str.find_first_of('P')>str.find_first_of('T'))
            flag=false;

        //计算三个位置A的个数
        int numA_1,numA_2,numA_3;
        numA_1=str.find_first_of('P');
        numA_2=str.find_first_of('T')-str.find_first_of('P')-1;
        numA_3=str.length()-str.find_first_of('T')-1;
        
        //位置2至少有一个A
        if(numA_2<1)
            flag=false;
        //a*b=c
        if(numA_1*numA_2!=numA_3)
            flag=false;

        if(flag)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }

    return 0;
}
上一篇下一篇

猜你喜欢

热点阅读