PATBasic——1040. 有几个PAT(25)

1040. 有几个PAT(25)

时间限制
120 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
CAO, Peng

字符串APPAPT中包含了两个单词“PAT”,其中第一个PAT是第2位(P),第4位(A),第6位(T);第二个PAT是第3位(P),第4位(A),第6位(T)。

现给定字符串,问一共可以形成多少个PAT?

输入格式:

输入只有一行,包含一个字符串,长度不超过105,只包含P、A、T三种字母。

输出格式:

在一行中输出给定字符串中包含多少个PAT。由于结果可能比较大,只输出对1000000007取余数的结果。

输入样例:
APPAPT
输出样例:

2

每次做PAT题,我都很赶时间,没弄清楚题意,就开始码代码,真是醉了。再次提醒自己,认真认真认真审题!!!

这题在纸上画一画,会比较容易找到思路。

1、一开始我想的是,从头到尾或者从后到前来遍历字符串,出现P时,计算A,出现A后,再找T,然后自己就晕了……然后又想从后往前找,找到第一个T,找第一个A,再找P……再次被自己搞晕了……

2、然后我又把字符串中每个字符对应的下标标出来了,一看,可以将PAT出现位置对应的数字都记下来,然后计算T>A>P这样条件的组合有多少,貌似是个排列组合的问题么?晕到是没晕,快速三个for循环嵌套,实现了……不过,运行超时!这么多for循环,相当于遍历字符串这么多次,不超时才怪!

3、最后一版本是正确思路。这个问题,其实应该拆分一下。以从后往前遍历为例,先找到T,找到AT组合的个数,再找PAT,这样可以把问题简化。T的个数,从找到第一个T开始++,然后找第一个A,这样AT的个数为原先T的个数,即numT,如果再遍历都没有遇到P,又遇到了A,则A个数为2,AT个数就变成了numT+numT(一个A对应了numT个AT)。一次类推就很好想了……PAT的个数,就等于加上numAT,每次遇到P,就加numAT. 最终的代码如下:

第二次代码:

#include<vector>
#include <sstream>
#include<cmath>
#include<iomanip>
#include<iostream>
#include <ctype.h>
#include <stdlib.h>

using namespace std;

int main()
{
	string s;
	cin >> s;
	int numT = 0;
	int numAT = 0;
	int numPAT = 0;
	int num = 1000000007;
	for (int i = s.length() - 1; i >= 0; i--)//从后往前进行遍历
	{
		char si = s[i];
		if (si == 'T')//找到T的个数
		{
			numT++;
		}
		else if (si == 'A')
		{
			numAT = (numAT + numT) % num;//计算AT个数,为后面T的个数,加当前A的个数
		}
		else
		{
			numPAT = (numPAT + numAT) % num;//与计算AT个数道理类似
		}
	}
	cout << numPAT;

	return 0;
}

第一次代码:

int main()
{
	//vector<int> Plocts;
	//vector<int> Alocts;
	//vector<int> Tlocts;

	int Plocts[33334] = { 0 };
	int Alocts[33334] = { 0 };
	int Tlocts[33334] = { 0 };

	int pc = 0, ac = 0, tc = 0;
	string s;

	//s = "APPAPTPAAPTPPATTTAPA";
	cin >> s;
	for (int i = 0; i < s.length(); i++)
	{
		char a = s[i];
		if (a == 'P')
		{
			Plocts[pc]=i;
			pc++;
		}
		else if (a=='A')
		{
			Alocts[ac]=i;
			ac++;
		}
		else if (a=='T')
		{
			Tlocts[tc]=i;
			tc++;
		}
	}

	int count = 0;

	for (int i = 0; i < pc; i++)
	{
		//int pl = Plocts[i];
		for (int j = 0; j < ac; j++)
		{
			//int al = Alocts[j];
			if (Alocts[j]>Plocts[i])//A的位置大于P,即A在P后面
			{
				for (int k = 0; k < tc; k++)
				{
					//int tl = Tlocts[k];
					if (Alocts[j]<Tlocts[k])
					{
						count = count + tc - k;
						break;
					}
				}
			}
		}
		
	}	
	if (count < 1000000007)
	{
		cout << count;
	}
	else
	{
		cout << count % 1000000007;
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值