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;
}

猜你喜欢

转载自blog.csdn.net/a656418zz/article/details/84257791