1. 程式人生 > >PAT (Basic Level) Practice 1003 我要通過!(兩種解法)

PAT (Basic Level) Practice 1003 我要通過!(兩種解法)

乙級1003
在這裡插入圖片描述
在這裡插入圖片描述
這題和HOJ3788一樣,故把那邊的sample也拿過來:
在這裡插入圖片描述
題意好理解,就對條件3解釋一下:
如果 aPbTc 是正確的,那麼 aPbATca 也是正確的,其中 a、 b、 c 均或者是空字串,或者是僅由字母 A 組成的字串。
就相當於是先對aPbATca進行操作成aPbTc,這一個新的字串再對條件1、2、3判斷,對於這時候的條件3,aPbTc又是一個新的“aPbATca”,所以在條件3的操作方法一樣

先介紹一下自己頭次看到這題的想法,純暴力模擬原題
先排除其它情況
1.如果有PAT之外的字
2.如果P、T出現2次以上或者1次都沒出現+沒有A
3.如果T前面不是A(判斷P後面是不是A可能會有陣列溢位的危險)
4.字串長度不足3的

條件1,直接強行各元素一一對應就行
條件2,xPATx,也就是P左邊的A和T右邊的A數量一樣即可
條件3,先拿出aPbATca,要找到a,bA,ca的位置,這時候我們就有了分開來的這三個組合,將它重組成aPbTc就可以了,然後組成的aPbTc再進行條件1、2、3的判斷
純模擬,對字串的分解構成操作了很多,程式碼上有部分註釋 還算能理解
模擬題就是要注意如果出什麼樣例與結果不符了的話,要一步一步慢慢除錯,一個分號都不能打錯!
AC程式碼:

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int is1(char *p,int len);
int is2(char *p,int len);
int is3(char *p,int len);
int newlen; 
int main(){
	int n;
	cin>>n;
	char pat[102];
	while(n--){
		scanf("%s",&pat);
		int len = strlen(pat);
		if(is1(pat,len)||is2(pat,len)||is3(pat,len)){
//			printf("is1 = %d\n",is1(pat,len));
//			printf("is2 = %d\n",is2(pat,len));
//			printf("is3 = %d\n",is3(pat,len));
			
			printf("YES\n");
		}else
			printf("NO\n");
	}
	return 0;
}
int is1(char *p,int len){
	if(len==3){
		if(p[0]=='P'&&p[1]=='A'&&p[2]=='T') 
			return 1;
	}
	return 0;
}
int is2(char *p,int len){
	int p_pos = 0;
	for(int i = 0;i<len;i++){
		if(p[i]!='P'&&p[i]!='A'&&p[i]!='T')
			return 0;
		if(p[i]=='P'&&i+2<len&&p[i+1]=='A'&&p[i+2]=='T'){
			p_pos = i;
		}
	}
	if(p_pos+p_pos+3!=len||p_pos == 0)
		return 0;
	for(int i = 0;i<p_pos;i++){
//		printf("p[%d] = %c\n",i,p[i]);
		if(p[i]!='A')
			return 0;
		else{
			if(p[i]!=p[i+p_pos+3])
				return 0;
		}
	}
	return 1;
}
int is3(char *p,int len){//aPbATca --> aPbTc
	int p_pos=-1;
	int a_pos=-1;
	int t_pos=-1;
	int onlyt=0,onlyp=0;
	for(int i = 0;i<len;i++){
		if(p[i]!='P'&&p[i]!='A'&&p[i]!='T')
			return 0;
		if(p[i]=='P'){//只有一個P 
			if(onlyp){
				return 0;
			}
			p_pos = i;
			onlyp = 1;
		}
			
		if(i>=1&&p[i]=='T'){//只有一個T 
			if(onlyt){
				return 0;
			}
			t_pos = i;
			onlyt = 1;
			if(p[i-1]=='A'){//T前面必須是A 
				a_pos = i-1;
			}else return 0; //否則退出沒寫,一直卡著我的bug位置所在。。
			
		}
	} 
	if(p_pos==-1||a_pos==-1||t_pos==-1)
		return 0;
	newlen = a_pos+len-p_pos-t_pos;
	
//	printf("p_pos = %d    a_pos = %d    t_pos = %d    newlen = %d\n",p_pos,a_pos,t_pos,newlen);
	char aPbTc[newlen];
	
	int pos = 0;
	for(pos ; pos <= p_pos ; pos++){//aP
		aPbTc[pos] = p[pos];
//		printf("p[pos] = %c\n",p[pos]); 
	}
	
	
	
	int lenb = a_pos - p_pos - 1;
//	printf("a_pos = %d   p_pos = %d   lenb = %d \n",a_pos,p_pos,lenb);
	for(int i = 0;i<lenb;i++){  //aPbT
		aPbTc[pos] = 'A';
		pos++;
	}
	aPbTc[pos++] = 'T';
	
	int lenc = len - p_pos - t_pos - 1;
	
//	printf("lenc = %d\n",lenc);
	for(int i = 0;i<lenc;i++){
		aPbTc[pos++] = 'A';
	}
	
//	for(int i = 0 ;i<newlen;i++){
//		printf("%c",aPbTc[i]);
//	}
//	cout<<endl;
	
//	printf("is1 = %d\n",is1(aPbTc,len));
//	printf("is2 = %d\n",is2(aPbTc,len));
			
	if(is1(aPbTc,newlen)||is2(aPbTc,newlen)||is3(aPbTc,newlen)){
		return 1;
	}
	return 0;
}

再講一下另一個思路:找規律
第一次看的時候看不出規律,第二次看的時候發現了……所以如果遇到一個非常複雜的模擬題可以先放一放,有可能這題會有特殊的規律
針對條件3,首先要明白aPbATca轉換成aPbTc後,這個新的字串也可能還是aPbATca的格式
然後針對這個操作再詳細思考一下:
我們從aPbATca轉換成aPbTc,實質上是去掉了b+A的一個A,以及c+a的一個a。
如果條件1、2不通過,繼續條件3下去,每次都是去掉b+A的一個A,c+a的一個a
去掉最後,肯定是以條件1和條件2為出口出去,那就是說,去掉最後肯定是
xPATx的格式(x=null即條件1)
再將其轉換成aPbTc,那就是此時我的B=一個A,a=c
然後往回推成aPbATca,最左邊的a不變,每一次b加一個A,c加一個a
推回到原字串,P和T之間我每加n個A,T後面的字串內容就是n*a
那就是說 只要我的a*b = c

那它就是一個合格的字串
AC程式碼:

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int p_pos = -1;
int t_pos = -1;
int a_pos = -1;
int isright(char *a,int len){//字串格式確認 
	int onlyp = 0;
	int onlyt = 0;
	for(int i = 0;i < len;i++){
		if(a[i]!='P'&&a[i]!='A'&&a[i]!='T') return 0;
		else{
			if(a[i]=='P'){
				if(onlyp)	return 0;
				else 		{onlyp = 1;	p_pos = i;}
			}
			if(a[i]=='T'){
				if(onlyt)	return 0;
				else {
					onlyt = 1;
					t_pos = i;
					if(a[i-1]=='A')	a_pos = i-1;
					else return 0;
				}
			}
		}
	}
	if(!onlyp||!onlyt)	return 0;
	return 1;
}
int main(){
	int n;
	cin>>n;
	char pat[102];
	while(n--){
		scanf("%s",&pat);
		int len = strlen(pat);
		int wellplay = 0; 
		if(isright(pat,len)){
			int lena = p_pos;
			int lenb = a_pos - p_pos - 1;
			int lenca = len - t_pos - 1;
			int lenc = lenca - lena;
			if(lenb*lena==lenc){
				wellplay = 1;
			}
		}
		if(wellplay)
			printf("YES\n");
		else
			printf("NO\n");
	} 
	return 0;
}