要看题的点进去吧
这里直接说思路和代码。
思路
直接暴力会超时。
换个角度思考问题,对一个确定位置A来说,以它形成的PAT个数等于它左边P的个数乘以它右边T的个数。例如字符串APPAPT的中间那个A来说,它左边有两个P,右边有一个T,因此这个A能形成的PAT个数就是2X1=2。于是问题就转化为,对字符串中间的每个A,计算它左边P的个数与它右边T的个数的乘积,然后把所有的A的这个乘积相加就是答案。
那么,有没有比较快的获得每一位左边P的个数的方法呢?当然有,只需要设定一个数组leftNumP,记录每一位左边P的个数(含当前位,下同)。接着从左到右遍历字符串,如果当前位i是P,那么leftNumP[i]就等于leftNum[i-1]加一;如果当前位i不是P那么leftNumP[i]就等于leftNumP[i-1]。于是只需要O(len)的时间复杂度就能统计出leftNumP数组。
同样的方法可以计算出每一位右边T的个数。为了节省代码量,不妨在统计每一位右边个数T的过程中直接计算出答案ans。
具体做法是:定义一个变量rightNumT,记录当前累计的右边T个数。从右往左遍历字符串,如果当前位i是T,那么令rightNum加1;否则,如果当前位i是A,那么令ans加上leftNumP[i]与rightNumT的乘积(注意取模)。这样,当遍历完字符串时,就得到了答案ans
代码的变量名可能与上述变量有出入
AC代码:
#include<cstdio>
#include<cstring>
int main()
{
char str[100010];
scanf("%s",&str);
int n = strlen(str);
int a[n] = {0};
for(int i = 0 ; i < n ; i++)
{
if(i>0)
a[i]=a[i-1];
if(str[i]=='P')
a[i]++;
}
int ans=0,rightnum=0;
for(int i = n - 1;i>=0;i--)
{
if(str[i]=='T'){
rightnum++;}
else if(str[i] == 'A')
{
ans = (ans+a[i]*rightnum) % 1000000007;
}
}
printf("%d",ans);
}