题目链接:1003 我要通过!
思路分析:
1、字符串中必须仅有 P
、 A
、 T
这三种字符,不可以包含其它字符
分析:字符串只能由这三种字符组成,在判断的过程中,如果出现了其他字符,那么该字符串不符合规范。
2、任意形如 xPATx
的字符串都可以获得“答案正确”,其中 x
或者是空字符串,或者是仅由字母 A
组成的字符串;
分析:
(1)当x表示空的时候,字符串表示的是PAT,字符串是正确的
(2)当x表示A的时候,字符串表示的是APATA,字符串是正确的
(3)当x表示AA的时候,字符串表示的是AAPATAA,字符串是正确的
(4)当x表示AAA的时候,字符串表示的是AAAPATAAA,字符串是正确的
(5)后面依次类推,注意P的前面和T的后面都是x,表达的意思就是P前面A的数量和T后面A的数量是一样的。
3、如果 aPbTc
是正确的,那么 aPbATca
也是正确的,其中 a
、 b
、 c
均或者是空字符串,或者是仅由字母 A
组成的字符串。
(1)P前面是a,P和T之间是b,T后面是c;a,b,c是由A组成的字符串或者空串,a,b,c三者之间可以相同,也可以完全不同。
(2)可不可以三者都是空串呢?根据测试用例PT得到的结果是NO,PAT得到的是YES,可以看出,P和T之间一定要有A。
(3)根据第(2)点,我们可以看出,P和T之间一定要有A,P的前面和T的后面可以是空,那么中间A是否只能有一个呢?根据测试样例PAAT是YES,PAT也是YES,可以推测,PxT都是对的,其中x由A组成,且至少有一个A,可以有多个A。
(4)在第(3)点中,我们推测,当P前面和T后面都是空串的时候,P和T之间至少要有一个A。那aPbTc中,可以确定b不可以为空串,a,c可以为空串。根据题目意思aPbATca也是对的,我们和aPbTc对比,P和T之间加了一个A,T后面加了一个a。那么推测,当P和T之间再加一个A,得到的是aPbAATcaa,当P和T之间再加一个A,得到的是aPbAAATcaaa,并且b也是由A组成的字符串。
(5)在第(4)点中,我们可以得到aPbTc是正确的,那么aPbAAATcaaa也是正确的。接下来看测试用例,AAPATAA是正确的,此时a是AA,b是A,c是AA。b由一个A组成,那么c=a。AAPAATAAAA是正确的,此时a是AA,b是AA,c是AAAA,c可以看作是由两个a组成。APAAATAA是错误的,此时a是A,b是AAA,c是AA。
(6)我们结合xPATx中x由若干个A组成正确的,因此aPbTc中当b等于一个A的时候,a等于c,aPbTc可以写成aPbTa。aPbTc中P和T之间每增加一个A,最末尾增加一个c,可以将P和T之间字符串b可以拆分成A+若干个A,那么aPbTc就变成了aPA+(若干个A)Ta+(若干个a),进行总结,aPbTc可以写成aP(N个A)T(N个a),也就是c=(b中A的数量)*a,由于a、b、c都是由A 组成的字符串。因此a,b,c三者之间的关系是len(c) = len(b)*len(a),也就是a中A的数量*b中A的数量=c中A的数量。
最后我们根据测试用例总结一下正确的字符串应该具备的条件:
(1)字符串只能由P、A、T三种字符组成(根据题目给出的条件一和测试用例xPATx错误、测试用例Whatever错误得出)
(2)字符串P、A、T三种字符必须都出现,P和T之间一定要有A(根据测试用例PT错误、APT错误、PAT正确、PAAT正确得出)
(3)字符串P和T只能出现一次(根据测试用例APATTAA错误得出)
(4)P在T的前面(根据PAT正确、PAAT正确、AAPATAA正确、AAPAATAAAA正确得出)
(5)P前面A的数量*P和T之间A的数量=T后面A的数量(根据PAT正确、PAAT正确、AAPATAA正确、AAPAATAAAA正确、APAAATAA错误得出)
代码一:
def judge(s):
cnt_p,cnt_a,cnt_t = 0,0,0
index_p,index_t = -1,-1
for i in range(len(s)):
c = s[i]
#如果有非P A T 字符,那么该字符串不符合要求
if c != 'P' and c != 'A' and c != 'T':
#print(s)
return False
if c == 'P':
cnt_p += 1
index_p = i
if c == 'A':
cnt_a += 1
if c == 'T':
cnt_t += 1
index_t = i
#如果有P或者A字符的数量大于1,那么该字符串不符合要求
if cnt_p > 1 or cnt_t > 1:
#print(s)
return False
#如果有P和T之间没有字符A,那么该字符串不符合要求
if index_p+1 == index_t:
#print(s)
return False
#如果有P在T后面,那么该字符串不符合要求
if index_p > index_t:
#print(s)
return False
n = int(input())
for _ in range(n):
s = input()
if judge(s) == False:
#print(s)
print('NO')
continue
index_p = s.find('P')
index_t = s.find('T')
# print('{} {} {} {} {}'.format(index_p,index_t,index_p,index_t - index_p - 1,len(s) - index_t-1))
#如果P前面的A的数量(index_p) * P和T之间的A的数量(index_t - index_p - 1) = T后面A的数量(len(s) - index_t-1)
if index_p * (index_t - index_p - 1)== len(s) - index_t-1:
print('YES')
else:
print('NO')
方法二:使用正则表达式
根据题目意思:
(1)P前面有零个或者多个A,为A*P
(2)T后面有零个或者多个A,为TA*
(3)P和T之间至少有一个A为,PA+T
(4)整个字符串只有一个P和T
(5)因此整个字符串模板为:A*PA+TA*
(6)根据P和T进行分段a=re.split(r'[P|T]',s)
(6)符合这个模式的字符串进一步判断:P前面A的数量*P和T之间A的数量=T后面A的数量是否成立。len(a[0])*len(a[1])==len(a[2])是否成立
import re
n=input()
for i in range(int(n)):
s=input()
if re.match(r'A*PA+TA*',s): #在字符串中进行匹配
a=re.split(r'[P|T]',s) #以字符P,T进行分段
#print('{} {} {}'.format(a[0],a[1],a[2]))
if len(a[0])*len(a[1])==len(a[2]): #条件判断
print('YES')
else:
print('NO')
else:
print('NO')