目录
1040:有几个PAT
字符串 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
代码长度限制
16 KB
时间限制
150 ms
内存限制
64 MB
思路:
1.暴力
我们可以进行暴力枚举,找到一个字符'P'之后,就向后枚举后面有几对'AT',找到就讲一个计数变量+1,最后输出.(解析详见代码)
1.2代码:
//1040有几个PAT:
//暴力法
#include<bits/stdc++.h>
using namespace std;
long long add(string a,int l,int r){ //查找'T'
long long sum=0; //记录'T'出现的个数
for(int i=l;i<r;i++)
if(a[i]=='T')
sum++; //出现就加起来
return sum; //返回'T'的个数
}
long long pd(string a,int l,int r){ //查找'A'
long long sum=0; //记录'A'出现的次数
for(int i=l;i<r;i++)
if(a[i]=='A')
sum+=add(a,i+1,r); //在add函数里面找'T'的个数
return sum; //返回'A'和'T'匹配的个数
}
long long check(string a){ //查找'P'
long long sum=0; //记录出现PAT的次数
int t=a.size(); //求a的长度
for(int i=0;i<t;i++) //枚举查找
if(a[i]=='P')
sum+=pd(a,i+1,t); //在pd函数里面查找'A'+'T' 的个数
return sum;
}
int main(){
string a;
cin>>a; //输入这个字符串
cout<<check(a)%1000000007<<endl;
return 0;
}
//时间复杂度O(logN^3)
//题目要求的是10^5,10^5^3=10^15,百分百绝对超时
//必须得优化,怎么优化?
2.优化
对字符串APPAPT来说
我们每次来统计'P'的个数
因为我们是找'PAT',必须要有'T'
所以对于APPAPT找到了T之后
P=3;
每次找到'P'之后,只能和他右边的来匹配
所以我们可以定一下,如果找到'A',可以和前面的'P'来匹配,相当于加上当前'P'的个数
如果输入APPAPT,我们可以每一个字符的遍历
过程:
0:A
P=0;
A=A+P=0;
1:P
P=1;
2:P
P=2;
3:A
A=A+P=2;
这个是遍历到了APPA这里,对于APPA里面的第二个'A'来说,它可以和前面两个'P'来匹配
4:P
P=3;
5:T
T=T+A=2;
找到'T'了, 就加上前面可以匹配上的已经匹配了的'P'和'A'
结束:
输出T,为2;
2.2代码:
//1040有几个PAT:
//正解:
#include<bits/stdc++.h>
using namespace std;
int main(){
int LIM=1000000007; //取余
int P=0,PA=0,PAT=0; //P是记录P的个数,PA是记录两者匹配的个数,PAT是记录'PAT'的个数
char c;
while((c=getchar())!= '\n'){ //getchear是读取一个字符,如果不为回车,就继续输入
if(c=='P')
P++;
if(c=='A')
PA+=P;
if(c=='T') //因为是'PAT'中的最后一个字符
PAT+=PA; //所以我们可以将前面统计到的'PA'的统计数目加进来
} //逆序思想,和暴力不同
printf("%d",PAT);
return 0;
}
//时间复杂度O(N)
总结:
这道题看起来不难,第一眼就会想到枚举,但是那肯定是要超时的,所以我们要进行优化,对以后的任何题目也是如此.