這是活用遞推裏面比較經典的一種題型;
若是採用最簡單的暴力枚舉,則會出現time limited錯誤。
這道題關鍵是可以找到遞推的思路。對於序列中的每個每個A,若是可以有PAT出現,則一定A的左右都有P和T;若是A左邊有a個P,右邊有b個T,則能夠推出含有該A的PAT有a*b個;因此解法就被分解成如下幾個步驟:
1.尋找左邊P的個數;
2.尋找右邊T的個數;
3.遍歷A,進行左右的乘積;
至於P和T個數的保存,咱們能夠仿照迪傑斯特拉算法中的distance數組來進行構造;
首先對於保存P的數組,進行輸入數組的遍歷,每一次從前一位繼承P的數目,若是該位爲P,則數目加一,從而構成一個保存的P的數組,其中index索引處的值表明輸入序列index位的左邊P的個數;
相關代碼以下:算法
int len=strlen(str); for(int i=0;i<len;i++){ if(i>0){ leftNumP[i]=leftNumP[i-1]; } if(str[i]=='P'){ leftNumP[i]++; } }
對於T,則不必構建數組,由於能夠在計數的同時從後往前遍歷,這樣就將第三第四步結合在了一塊兒;
相關代碼以下;數組
nt ans=0,rightNumT=0; for(int i=len-1;i>=0;i--){ if(str[i]=='T'){ rightNumT++; }else if(str[i]=='A'){ ans=(ans+leftNumP[i]*rightNumT)%MOD; } }
從而能夠經過一次遍歷完成後兩步的任務;
整體代碼以下所示:code
#include<cstdio> #include<stdlib.h> #include<cstring> const int MAXN=100010; const int MOD=1000000007; char str[MAXN]; int leftNumP[MAXN]={0}; int main(){ scanf("%s",str); int len=strlen(str); for(int i=0;i<len;i++){ if(i>0){ leftNumP[i]=leftNumP[i-1]; } if(str[i]=='P'){ leftNumP[i]++; } } int ans=0,rightNumT=0; for(int i=len-1;i>=0;i--){ if(str[i]=='T'){ rightNumT++; }else if(str[i]=='A'){ ans=(ans+leftNumP[i]*rightNumT)%MOD; } } printf("%d\n",ans); system("pause"); return 0; }