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 Afor(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的个数那么多的组合。