PAT B1040有几个PAT(递推)

1. 问题描述:

字符串APPAPT中包含了两个单词"PAT",其中第一个PAT是由第二位(P),第四位(A),和第六位(T)组成的,第二个PAT是由第三位(P)、第四位(A),和第六位(T)组成的,现给定字符串,问一共可以形成多少个PAT?

2. 思路分析:

① 假如使用暴力破解依次遍历字符串来判断是否形成了PAT,那么肯定是超时的

② 我们可以使用另外一个思路来思考问题,对于一个确定的位置A来说,以它形成PAT的各式等于它左边的P的个数乘以右边T的个数,假如对字符串APPAPT中间那个A来说,它左边有两个P,右边有一个T,因此这个A能形成的PAT的个数就是2 * 1 = 2,于是问题就转化为对字符串中的每一个A计算它左边P的个数和右边T的个数的乘积,然后把所有A的乘积加起来就是我们需要求解的结果

③ 我们在求解左边P的个数的时候,可以设置一个数组leftNumP来记录当前i位置左边p的个数,从左边遍历字符串,如果当前位i是P,那么leftNumP[i]等于leftNumP[i - 1] + 1,如果不是P那么等于上一个位置的P的个数,我们在从右往左计算的时候为了节省代码量可以在遍历的时候计算出答案,定义一个遍历rightNumT记录当前位置有多少个T了,假如不是T是A那么让ans加上leftNumP[i] * rightNumT的值

④ 上面的思路正是体现了递推的思想,我们在思考问题的时候需要培养出这样的思维,因为假如我们使用递归可以解决的时候,可以跟暴力破解消耗的时间就不是在一个数量级上的了

3. 下面是具体的代码:

#include<stdio.h>
#include<cstring>
const int maxn = 100010;
const int MOD = 1000000007;
char str[maxn];
int leftNumP[maxn] = {0};
int main(void){
	gets(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 + rightNumT * leftNumP[i]) % MOD;   
		}
	}
	printf("%d\n", ans);
	return 0;
}
发布了498 篇原创文章 · 获赞 133 · 访问量 50万+

猜你喜欢

转载自blog.csdn.net/qq_39445165/article/details/94896404
今日推荐