1003 我要通过!
题目
“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于 PAT 的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。
得到“答案正确”的条件是:
- 字符串中必须仅有
P
、A
、T
这三种字符,不可以包含其它字符; - 任意形如
xPATx
的字符串都可以获得“答案正确”,其中x
或者是空字符串,或者是仅由字母A
组成的字符串; - 如果
aPbTc
是正确的,那么aPbATca
也是正确的,其中a
、b
、c
均或者是空字符串,或者是仅由字母A
组成的字符串。
现在就请你为 PAT 写一个自动裁判程序,判定哪些字符串是可以获得“答案正确”的。
输入格式:
每个测试输入包含 1 个测试用例。第 1 行给出一个正整数 n (<10),是需要检测的字符串个数。接下来每个字符串占一行,字符串长度不超过 100,且不包含空格。
输出格式:
每个字符串的检测结果占一行,如果该字符串可以获得“答案正确”,则输出 YES
,否则输出 NO
。
输入样例:
8
PAT
PAAT
AAPATAA
AAPAATAAAA
xPATx
PT
Whatever
APAAATAA
输出样例:
YES
YES
YES
YES
NO
NO
NO
NO
思路1
好久没做这么费体力的题了,清明假期浪了几天,有点,emmmm,算是做了好几天的题吧,现在答案部分正确。
题目给了三个条件,前两个很简单,条件一
- 字符串中必须仅有
P
、A
、T
这三种字符,不可以包含其它字符;
是必要条件,条件二
任意形如
xPATx
的字符串都可以获得“答案正确”,其中x
或者是空字符串,或者是仅由字母A
组成的字符串;
是解题关键,从条件三
如果
aPbTc
是正确的,那么aPbATca
也是正确的,其中a
、b
、c
均或者是空字符串,或者是仅由字母
A
组成的字符串。
可以看出,答案要么满足条件二,要么可以转换为条件二,也就是xPATx
思路如下:
1、拿到字符串,先判断是否符合条件一,再看是否符合条件二,而且隐藏条件就是P
和T
都有且只有出现一次,答案一中未体现,导致出现2错误,修正部分在答案2,修正后4正确2超时。如果符合条件二则输出YES
,否则执行下一步。
2、如果给的是aPbATca
形,则去掉它中间的A
和后面的a
,转换成aPbTc
形,迭代至b
只有一个A
时,判断是否符合xPATx
形,并输出结果。
其中由于a
、 b
、 c
只含有A
,P和T只出现一次,所以可以从aPbATca
形中解析出a
,再分解出 c
,b
就很简单了,P
和T
中间除掉一个A
就是b
了。
思路2
这个思路来自百度,果然dalao多,直接看呆了我。
- 首先,不管什么形,看成
aPbTc
,不符合这个形直接out。 - 然后,
a
只能由A
组成,A
的个数可以是任意大于等于0的整数。记A
的个数n1
。b
只能由A
组成,个数可以是任意大于等于1的整数。记个数n2
。c
只能由A
组成,个数可以是任意大于等于0的整数。记个数n3
。 - 到这里没问题的话,直接验证, n 1 × n 2 = = n 3 n1\times n2==n3 n1×n2==n3 等式成立则YES,否则NO
这个等式的来源是这样的。假如给的是可以YES的字符串aPbATca
,可以通过去掉它中间的A
和后面的a
,转换成aPbTc
形,通过迭代总是可以变成xPATx
形,此时n1
与n2
,n3
的关系成立。将xPATx
往原式逆推一次则为xPAATxx
,两次为xPAAATxxx
,中间A
的数量总会等于T后x的数量。从而可以得到
n
1
×
n
2
=
n
3
n1\times n2=n3
n1×n2=n3。
对应答案4,代码量少了一大半,niubility。
答案1(2正确,2错误,2超时。2020-4-7 21:52:33)
#include <stdio.h>
int isOnlyPAT(char str[])
{
int i = 0;
while(str[i]!='\0')
{
if(str[i]!='P'&&str[i]!='T'&&str[i]!='A')
return 0;
i++;
}
return 1;
}
int isxPATxform(char str[])
{
int i = 0;//point at front
int j = 0;//point at tail
while(str[j]!='\0')
{
j++;
}
j--;
while(str[i++]==str[j--]);
i--;
j++;
//printf("%d%d",i,j);
if(str[i]=='P'&&str[i+1]=='A'&&str[i+2]=='T'&&i+2==j)
{
return 1;
}else
{
return 0;
}
}
int isOkToChangeaPbTcPass(char str[])
{
/*
if aPbTc ok,then aPbATca OK
and original aPbTc shoulb be xPATx form
1.from aPbATca we can prase out a,b and c
2.and then recombination to aPbTc,
3.if the aPbTc isn't the xPATx form then repeat above steps
4.if fail to repeat then return false
*/
char a[100];
char c[100];
char newstr[100];
if(isxPATxform(str))
{
return 1;
}
//prase a
int i=0;
while(str[i]=='A')
{
a[i] = str[i];
i++;
}
a[i] = '\0';
if(str[i] != 'P')
{
return 0;
}
i--;
//printf("sdf");
//prase c and confime the aPbATca form
int j = 0;
while(str[j]!='\0')
{
j++;
}
j--;//j point at tail
while(i>=0)
{
if(a[i]==str[j])
{
i--;
j--;
}
}
//j point at c tail
int k = 0;
while(str[k]!='T')
{
k++;
}
k++;
//k point at c front
i=0;
for(k;k<=j;k++)
{
c[i++] = str[k];
}
c[i] = '\0';
//phrase c done
//constract newstr
i = 0;
while(a[i]!='\0')
{
newstr[i] = a[i];
i++;
}
newstr[i] = 'P';
i++;
while(str[i] != 'T')
{
newstr[i]=str[i];
i++;
}
i--;
newstr[i] = 'T';
i++;
j = 0;
while(c[j]!='\0')
{
newstr[i] = c[j];
i++;
j++;
}
newstr[i] = '\0';
if(isxPATxform(newstr)==1)
return 1;
else
return isOkToChangeaPbTcPass(newstr);
}
int main(int argc, char* argv[])
{
char string[101] = {"AAPAAATAAAAAA"};
int n;
int i = 0;
scanf("%d",&n);
for(i = 0; i < n ;i++)
{
scanf("%s",&string);
if(isOnlyPAT(string)==1&&isOkToChangeaPbTcPass(string)==1)
{
printf("YES\n");
}else
{
printf("NO\n");
}
}
//printf(isOkToChangeaPbTcPass(string)?"true\n":"false\n");
return 0;
}
答案2(4正确2超时,2020-4-7 22:34:55)
// only revise this function
int isOnlyPAT(char str[])
{
int i = 0;
while(str[i]!='\0')
{
if(str[i]!='P'&&str[i]!='T'&&str[i]!='A')
return 0;
i++;
}
//add this part
int countT = 0;
int countP = 0;
i = 0;
while(str[i]!='\0')
{
if(str[i]=='P')
countP++;
if(str[i]=='T')
countT++;
i++;
}
if(countT == 1 && countP == 1)
return 1;
else return 0;
//add end
}
答案3(全正确,2020-4-7 23:08:05)
将记录a
和c
的字符串修改成记录只记录a
和c
的长度,就不超时了。
#include <stdio.h>
int isOnlyPAT(char str[])
{
int i = 0;
while(str[i]!='\0')
{
if(str[i]!='P'&&str[i]!='T'&&str[i]!='A')
return 0;
i++;
}
int countT = 0;
int countP = 0;
i = 0;
while(str[i]!='\0')
{
if(str[i]=='P')
countP++;
if(str[i]=='T')
countT++;
i++;
}
if(countT == 1 && countP == 1)
return 1;
else return 0;
}
int isxPATxform(char str[])
{
int i = 0;//point at front
int j = 0;//point at tail
while(str[j]!='\0')
{
j++;
}
j--;
while(str[i++]==str[j--]);
i--;
j++;
if(str[i]=='P'&&str[i+1]=='A'&&str[i+2]=='T'&&i+2==j)
{
return 1;
}else
{
return 0;
}
}
int isOkToChangeaPbTcPass(char str[])
{
/*
if aPbTc ok,then aPbATca OK
and original aPbTc shoulb be xPATx form
1.from aPbATca we can prase out a,b and c
2.and then recombination to aPbTc,
3.if the aPbTc isn't the xPATx form then repeat above steps
4.if fail to repeat then return false
*/
int n = 0 ; //longth of str
int counta=0;//a and c is only a string consist of a serise of 'A'
int countc=0;//we only need to count the number of it
char newstr[100];
if(isxPATxform(str))
{
return 1;
}
//count A number
int i=0;
while(str[i++]=='A');
i--;
counta = i;// number = index +1
if(str[i] != 'P')
{
return 0;
}
//count C number
int j = 0;
while(str[n]!='\0')
{
if(str[n] == 'T')
j = n;
n++;
}
countc = n - j - counta -1;
//printf("%d,%d\n",counta,countc);
//constract newstr
for(i = 0 ;i < counta; i++)
{
newstr[i] = 'A';
}
newstr[i++] = 'P';
while(str[i] != 'T')
{
newstr[i]=str[i];
i++;
}
i--;
newstr[i] = 'T';
i++;
for(j = 0;j < countc; j++)
{
newstr[i++] = 'A';
}
newstr[i] = '\0';
//printf("%s\n",newstr);
if(isxPATxform(newstr)==1)
return 1;
else
return isOkToChangeaPbTcPass(newstr);
}
int main(int argc, char* argv[])
{
char string[101] = {"AAPAAATAAAAAA"};
int n;
int i = 0;
scanf("%d",&n);
for(i = 0; i < n ;i++)
{
scanf("%s",&string);
if(isOnlyPAT(string)==1&&isOkToChangeaPbTcPass(string)==1)
{
printf("YES\n");
}else
{
printf("NO\n");
}
}
return 0;
}
答案4(2020-4-8 01:38:24)
#include <stdio.h>
int isOnlyPATLetter(char str[])
{
//and both P and T numbers only one
// and position of P before T, at least one A betweem
int i = 0;
while(str[i]!='\0')
{
if(str[i]!='P'&&str[i]!='T'&&str[i]!='A')
return 0;
i++;
}
//count T,count P
int countT = 0;
int countP = 0;
//position T and position P
int positionT = 0;
int positionP = 0;
i = 0;
while(str[i]!='\0')
{
if(str[i]=='P')
{
countP++;
positionP = i;
}
if(str[i]=='T')
{
countT++;
positionT = i;
}
i++;
}
if(countT == 1 && countP == 1 && (positionT - positionP > 1))
return 1;
else return 0;
}
int isN1TimesN2EqualN3(char str[])
{
/*
the form of str is aPbTc
define numbers of A in position of a N1
define numbers of A in position of b N2
define numbers of A in position of c N3
if N1 * N2 == N3 then return 1,else return 0
*/
int n1 = 0 ;
int n2 = 0 ;
int n3 = 0 ;
int i = 0 ;
while(str[i++]=='A');
n1 = i - 1;
while(str[i++]=='A');
n2 = i - 2 - n1;
while(str[i++]!='\0');
i--;
n3 = i - 2 - n1 - n2;
if(n1 * n2 == n3)
return 1;
else
return 0;
}
int main(int argc, char* argv[])
{
char string[101] = {'\0'};
int n;
int i = 0;
scanf("%d",&n);
for(i = 0; i < n ;i++)
{
scanf("%s",&string);
if(isOnlyPATLetter(string)==1&&isN1TimesN2EqualN3(string)==1)
{
printf("YES\n");
}else
{
printf("NO\n");
}
}
return 0;
}
总结
c语言没有bool类型,差点雷倒我。程序写的很慢,倒没什么卡壳调bug的地方。还是字符串,很繁复,需要慢慢理,我连把i++写在变量里边都怂。。。
搞定,等下去百度看看其他dalao的答案,很期待有人可以来一起交流一下,两个人讨论比一个人刷题有意思。