PAT乙级1040题解

题目详情:

1040 有几个PAT (25 分)
字符串 APPAPT 中包含了两个单词 PAT,其中第一个 PAT 是第 2 位 ( P ),第 4 位(A),第 6 位(T);第二个 PAT 是第 3 位( P ),第 4 位(A),第 6 位(T)。

现给定字符串,问一共可以形成多少个 PAT?

输入格式:
输入只有一行,包含一个字符串,长度不超过10的​5次方​​ ,只包含 P、A、T 三种字母。

输出格式:
在一行中输出给定字符串中包含多少个 PAT。由于结果可能比较大,只输出对 1000000007 取余数的结果。

输入样例:
APPAPT

输出样例:
2

思路:

本题最直接的解法就是三重循环遍历,但是显然时间复杂度过高,必定超时。对于本题,时间复杂度为n的三次方和n的平方都会超时,因为数据过大了。正确解法时间复杂度应为O(n)。我也是参考了很多大佬的解法才得以解决本题。

本题要求我们查找PAT的个数,显然我们不能一个一个去找(三重循环就是如此)这样效率太低了,我们可以通过字符个数的乘积来获取。假如题目不要求顺序,P,A,T三种字符的个数的乘积就是结果,而题目要求必须按照PAT的顺序,那么我们就要设定一个字母为标杆用来约束顺序,显然P与T不能作为标杆,因为若P为标杆,我们无法保证A与T的顺序,T同理,所以我们把A设定为标杆,这样可以确保A的前面为P,A的后面为T,也就约束了顺序。

我们可以先定义三个字母的计数器,用一个循环遍历字符串,获取T的个数,再建立一个循环遍历,若遍历到P,P计数器+1,遍历到T,T计数器-1(保证T在A后面),遍历到A,就将P与T的计数器相乘再取余1000000007,并加入sum。这样循环结束,sum即为所有PAT的个数。输出即可。

注意因为两个计数器的乘积显然是很可能大于int,所以要再次取余。

解答:

#include <iostream>
using namespace std;

int main()
{
    string str; cin >> str;
    int cntP = 0, cntT = 0, sum = 0;
    for(int i = 0; i < str.size(); i++){
        if(str[i] == 'T') cntT++;
    }
    for(int i = 0; i < str.size(); i++){
        if(str[i] == 'P') cntP++;
        if(str[i] == 'T') cntT--;
        if(str[i] == 'A') sum = (sum + (cntP * cntT) % 1000000007) % 1000000007;
    }
    cout << sum;
    return 0;
}
上一篇:PAT (Basic Level) Practice (中文)1040 有几个PAT (25 分)


下一篇:CCF 1040. 除法游戏