PAT-乙-1040 1040 有几个PAT (25 分)

在这里插入图片描述

代码

#include <iostream>

using namespace std; 

int main() {
	
	string s;
	cin>>s;
	int len = s.length(); //string length
	s = " " + s; 
	
	int countP[len+2] = {0}; // add: first last
	int countT[len+2] = {0}; // add: first last
	
	for(int i=1; i<=len; i++){
		if(s.at(i)=='P'){
			countP[i] = countP[i-1] + 1;
		}
		else{
			countP[i] = countP[i-1];
		}
	}
	
	for(int i=len; i>0; i--){
		if(s.at(i)=='T'){
			countT[i] = countT[i+1] + 1;
		}
		else{
			countT[i] = countT[i+1];
		}
	}
	
	long long int ans = 0;
	for(int i=1; i<=len; i++){
		if(s.at(i)=='A'){
			ans += countP[i] * countT[i];
			ans %= 1000000007; 
		}
	}
	
	cout<<ans<<endl;
	
	return 0;
}

注解

1、直接思路:从头到尾找P,找到一个P后,往后找A,找到一个A后,再往后找T。把所有找到的情况找出来即可。穷举肯定会超时。稍微变通一下,能不能找出每个P字符后面A的数量,每个A后面P的数量,存在数组里?看似可行,但确定P后面A的位置是至关重要的,因为不知道A的位置,就无法确定A后面T的具体数量。
2、转换思路!把刚才的以P为中心,转换成以A为中心。也就是从头到尾遍历找A,找到A后,看看A前面有多少P,后面有多少T,相乘起来就是结果了!这样就解决了刚才说的定位的问题,因为从头到尾遍历找A是容易的。
3、在具体实现时,为了保持一致,我们令字符串位置从1开始,因此手动增加了s.at(0)=’ ',也就是在0位置填了个空格。这样就使得下面这块代码可以保持优雅的一致性了。与此同时,我们开辟的countP和countT数组,也就是用来存某个A前面P数量和后面T数量的数组,也要多开2个单元,即0和last,否则会造成数组越界。如果不这样添加2个单元,开头结尾要单独处理,代码不优雅。

for(int i=1; i<=len; i++){
    		if(s.at(i)=='P'){
    			countP[i] = countP[i-1] + 1;
    		}
    		else{
    			countP[i] = countP[i-1];
    		}
    	}
    	
    	for(int i=len; i>0; i--){
    		if(s.at(i)=='T'){
    			countT[i] = countT[i+1] + 1;
    		}
    		else{
    			countT[i] = countT[i+1];
    		}
    	}

4、最后就是计算结果了,需要注意的是ans的类型,因为可能数量很大,建议用long long int存储。另外,每一步处理完毕后都求一个余数,也能避免数字过大溢出。

long long int ans = 0;
    	for(int i=1; i<=len; i++){
    		if(s.at(i)=='A'){
    			ans += countP[i] * countT[i];
    			ans %= 1000000007; 
    		}
    	}

结果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/zhanggirlzhangboy/article/details/82960713