PAT A1093

這是活用遞推裏面比較經典的一種題型;
若是採用最簡單的暴力枚舉,則會出現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;
}
相關文章
相關標籤/搜索