字符串 APPAPT
中包含了两个单词 PAT
,其中第一个 PAT
是第 2 位(P
),第 4 位(A
),第 6 位(T
);第二个 PAT
是第 3 位(P
),第 4 位(A
),第 6 位(T
)。
现给定字符串,问一共可以形成多少个 PAT
?
输入格式:
输入只有一行,包含一个字符串,长度不超过105,只包含 P
、A
、T
三种字母。
输出格式:
在一行中输出给定字符串中包含多少个 PAT
。由于结果可能比较大,只输出对 1000000007 取余数的结果。
样例:">输入样例:
APPAPT
输出样例:
2
思路:一开始我是想从前到后枚举P,然后P后面的第一个A,A后面的所有T,这样子三重循环去做,但是由于字符串长度是10万,所以On^3肯定会超时。
然后就是优化了:我们可以枚举中间的每一个A,然后看一下这个A前面的P的个数和这个A后面的T的个数,也就是要求不同位置上的AT的个数,那么自然我们就会想到前缀和模型了。
预处理:从1-字符串最后的每个位置的前面所有的A和T的个数,操作也很简单
首先当前的P或A的个数等于前面所有的个数之和 + 当前是否为P或T
#include <bits/stdc++.h>
using namespace std;
const int N = 100010, INF = 1000000007;
long long res;
int q[N], r[N];//q记录p, r记录T
int main()
{
string s = "1";
string s1;
cin >> s1;
s += s1;
int n = s1.size();
for (int i = 1; i <= n; i ++ )
{
q[i] += q[i - 1];
r[i] += r[i - 1];
if(s[i] == 'P') q[i] ++;
if(s[i] == 'T') r[i] ++;
}
for (int i = 1; i <= n; i ++ )
{
if(s[i] == 'A') res = (res + (q[i] * (r[n] - r[i - 1]))) % INF;
}
cout << res << endl;
return 0;
}