有不少题目须要细心考虑过程当中是否可能存在递推关系,若是能找到这样的递推关系,就能事时间复杂度降低很多。例如就这一类涉及序列的题目来讲,假如序列的每一位所须要的计算的值均可以经过该位左右两侧的结果计算获得,那么就能够考虑所谓的“左右两侧的结果”是否能经过递推动行预处理来获得,这样在后面的使用汇总就能够没必要反复求解。ios
例题:PAT乙级1040 / 甲级1093 有几个PATspa
字符串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
思路:code
直接暴力求解确定会超时。blog
换个角度思考问题,对一个肯定位置的A来讲,以它造成的PAT的个数等于它左边的p的个数乘以它右边T的个数。例如对字符串APPAPT的中间那个A来讲,它左边有两个P,右边有一个T,所以这个A能造成的PAT的个数就是2*1=2。因而问题就转换为:对自复查un中的每一个A,计算它左边的P的个数和右边的T的个数的乘积,而后把全部A的这个乘积相加就是答案。继承
代码以下:ci
#include <iostream> #include <string> using namespace std; int main(){ string str; cin>>str; int leftNum[110000]={0},rightNum=0; int result=0; for(int i=0;i<str.size();i++){ if(i>0){ leftNum[i]=leftNum[i-1];//继承上一个的个数,继续统计 } if(str[i]=='P') leftNum[i]++; } for(int i=str.size()-1;i>0;i--){ if(str[i]=='T'){ rightNum++; }else if(str[i]=='A'){ result=(result+leftNum[i]*rightNum)%1000000007; } } cout<<result; return 0; }