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
#include <cstdio>
#include <iostream>
#include <string>
#include <map>
#define YS 1000000007
using namespace std;
int main(){
map <int ,int> p,a,t;
string s;
cin>>s;
int size_s=s.size();
long long pos_p=0,pos_a=0,pos_t=0;
for(int i=0;i<size_s;i++){
if(s[i]=='P'){
p.insert(pair<int,int>(i,pos_p));
pos_p++;
}else if(s[i]=='A'){
a.insert(pair<int,int>(i,pos_a));
pos_a++;
}else if(s[i]=='T'){
t.insert(pair<int,int>(i,pos_t));
pos_t++;
}
}
map<int,int>::iterator iter1,iter2,iter3;
long long ans=0;
for(iter1=p.begin();iter1!=p.end();iter1++){//find a P
//find a A
for(iter2=a.begin();iter2!=a.end();iter2++){
if(iter2->first>iter1->first){
//how many T behind the A(iter2->first)
for(iter3=t.begin();iter3!=t.end();iter3++){
if(iter3->first>iter2->first){
ans=ans%YS+pos_t%YS-iter3->second%YS;
break;
}
}
}
}
}
cout<<ans<<endl;
return 0;
}
上面这段代码用暴力求解,循环得很笨拙,时间复杂度为O(n^3),大数据样例没有通过。
于是在网上看了看各路大神的题解,重新写了一下。
#include <cstdio>
#include <iostream>
#include <string>
#define YS 1000000007
using namespace std;
//之前的暴力求解,实在是不高效,遇到大数据分分钟崩
//现在这个思路是借用网上的某个思路的,逆序遍历,很简洁,思路也很清晰
int main(){
string s;
cin>>s;
int len=s.size();
int numT=0,numAT=0,numPAT=0;
for(int i=len-1;i>=0;i--){
if(s[i]=='T'){
numT++;
}else if(s[i]=='A'){
numAT=(numAT+numT)%YS;
}else{
numPAT=(numPAT+numAT)%YS;
}
}
printf("%d",numPAT);
return 0;
}
逆序遍历,既然要算有多少种PAT的可能,那么用逆序遍历,就可以通过数P后有多少个AT组合,A后有多少个T,来算得。
思路:
1.逆序数T的个数,在遇到一个A之时,之前数了有多少个T就有多少个AT.
2.若再次遇到A,则说明又有此A 之前数到的 T的个数那么多AT的组合。
3.若遇到P,则说明,有此P之前,数到的AT的个数那么多的组合。