1. 程式人生 > >PAT (Basic Level) Practice 1040 有幾個PAT

PAT (Basic Level) Practice 1040 有幾個PAT

乙級1040
在這裡插入圖片描述

如果順著想,找到一個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

,如果接下來找到一個A,那麼這個A和這兩個T都是能組成AT的
同樣的,在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;
}