题意:
给出一个字符串,可能有P、A、T或其他字符,现在需要根据以下几个条件来判断是否输出“YES”
条件1:如果出现P,A,T之外的字符,输出“NO”;初始状态下P和T必须各恰有一个,且P在T左边,P和T之间至少有一个A,否则输出“NO”
条件2:PAT,APATA,AAPATAA,AAAPATAAA,…,xPATx都输出“YES”,这里x为空或是任意数量的A
条件3:假设有一个字符串的格式是aPbTc,这里的a,b,c可以为空或是任意数量的A。如果这个字符串aPbTc已知是YES,那么在b和T之间添加一个A,c后面添加字符串a之后形成的新字符串aPbATca也是YES。
思路:
从图中可以看出,条件2给出的字符串是最底层YES的,且条件2的P与T中间有且只有一个A,而由条件3得到的所有字符串一开始一定是从条件2中的字符串变形而来。
所以我们记录P左边A的个数x,P和T中间A的个数为y,T右边A的个数为z。
考虑到条件3得到的新字符串的过程是在PT中间加一个A,字符串后面加上P前面所有的A,因此,我们每使用条件3一次,x不变,y=y+1,z=z+x。我们如果顺着箭头逆回去,每逆一次,x不变,y=y-1,z=z-x,这样一直逆到y=1,这时我们判断x和z是否相等,如果x==z,则输出“YES”,否则输出“NO”
因为y每次减1,所以要减到1,需要进行y-1次回退,而T右边的A的个数z在经过y-1次回退后(z每次减x)将变为z-x*(y-1)。我们只需要判断z-x*(y-1)==x是否成立即可。
代码如下:
#include<iostream>
#include<stdio.h>
#include<vector>
#include<string.h>
#define MAX 1000000
using namespace std;
int main(){
int T;
scanf("%d",&T);//输入字符串
getchar();
while(T--){
char str[110];
scanf("%s",str);
int len=strlen(str);
//分别代表P的个数、T的个数、除PAT外字符的个数
int num_p=0,num_t=0,other=0;
int loc_p=-1,loc_t=-1;//分别代表P的位置、T的位置
for(int i=0;i<len;i++){
if(str[i]=='P'){
num_p++;
loc_p=i;
}else if(str[i]=='T'){
num_t++;
loc_t=i;
}else if(str[i]!='A'){
other++;
}
}
//如果P的个数不为1,或者T的个数不为1,
//或者存在除PAT之外的字符,或者P和T之间没有字符
if(num_p!=1||num_t!=1||other!=0||(loc_t-loc_p)<=1){
printf("NO\n");
continue;
}
int x=loc_p,y=loc_t-loc_p-1,z=len-loc_t-1;
if(z-x*(y-1)==x){
printf("YES\n");
}else{
printf("NO\n");
}
}
return 0;
}