PAT (Basic Level) Practice 1040 有幾個PAT
如果順著想,找到一個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
同樣的,在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;
}