有不少題目須要細心考慮過程當中是否可能存在遞推關係,若是能找到這樣的遞推關係,就能事時間複雜度降低很多。例如就這一類涉及序列的題目來講,假如序列的每一位所須要的計算的值均可以經過該位左右兩側的結果計算獲得,那麼就能夠考慮所謂的「左右兩側的結果」是否能經過遞推動行預處理來獲得,這樣在後面的使用匯總就能夠沒必要反覆求解。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; }