如果顺着想,找到一个P,开始寻找下一个A,然后继续遍历有几个T,遍历完回去从第二个A继续遍历有几个T再加上去,直到A全部遍历完,这是一轮。
一个for是P,一个for是A,一个for是T,复杂度都至少O(n³)了,且时间限制是150ms,肯定超时,所以这个方法不可取
正确思路:对于每一个AT,都可以和一个P组成PAT,那么先考虑AT的组成,顺着想肯定不可能,那么就逆着想试试:
题目的样例太简单,我们来个长一点的
APPAPTTA
1.从后往前遍历,先找到一个T
2.然后前面找到一个A,那么这个A就能和我的T组合成AT
3.那么接下来继续往前找,找到P那么就表示能和P组成PAT
在1->2的过程中,如果我们又找到了额外的T,那么保存一下我们目前找到的T的数量为countT,如果接下来找到一个A,那么这个A和这两个T都是能组成AT的
同样的,在2->3的过程中,我们每多找到一个A,即又找到了countT个组合,对于整体来说,可以记为countAT = countT + countAT,这样的countAT,每找到一个P,都可以组成countAT个PAT,可以记为countPAT = countAT + countPAT
实例模拟:
APPAPTTA
第一个找到的是A,没关系,因为这个时候countT=0,所以大胆加上去,
countAT = countAT + countT = 0
第二个找到的是T,countT++
第三个是T,countT++
第四个是P,这时候countAT还是0,
countPAT = countAT + countPAT = 0
第五个是A,由于前面我们已经有2个T了,所以可以组成2个AT,公式照样
countAT = countAT + countT = 0 + 2 = 2
第六个是P,前面我们已经有2组AT了,可以组成2个PAT,代入公式
countPAT = countAT + countPAT = 2 + 0 = 2
第七个还是P,前面依然是2组AT
countPAT = countAT + countPAT = 2 + 2 = 4
第八个是A,前面有2个T,所以可以再组成2个AT
countAT = countAT + countT = 2 + 2 = 4
遍历结束,输出countPAT即可
代码实现:
#include<iostream>
#include<string.h>
#include<stdlib.h>
using namespace std;
int main(){
char str[100010];
scanf("%s",&str);
int len = strlen(str);
// cout<<"len = "<<len<<endl;
int ct=0,cat=0,cpat=0;
while(len--){//从后往前遍历,T -> A -> P 这样能成为一组,先找T->A能组成的数量
// cout<<"str[len] = "<<str[len]<<endl;
if(str[len] == 'T'){//找到一个T就ct++
ct++;
} else if(str[len] == 'A') {//找到一个A,这一个A可以和后面所有的T并成一组AT,所以cat = cat + ct,有几个A就多加几个T
cat = cat + ct;
if(cat>1000000007) cat = cat%1000000007;
} else {//道理同A,有几个P就多加几个AT
cpat = cpat + cat;
if(cpat>1000000007) cpat = cpat%1000000007;
}
}
cout<<cpat<<endl;
return 0;
}