Python编程基础题(21-我要通过!)

Description
“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于 PAT 的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。 得到“答案正确”的条件是:

  1. 字符串中必须仅有 P、 A、 T这三种字符,不可以包含其它字符;
  2. 任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x或者是空字符串,或者是仅由字母 A 组成的字符串;
  3. 如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a、 b、 c 均或者是空字符串,或者是仅由字母 A 组成的字符串。 现在就请你为 PAT 写一个自动裁判程序,判定哪些字符串是可以获得“答案正确”的。

Input
每个测试输入包含 1 个测试用例。第 1 行给出一个正整数 n (<10),是需要检测的字符串个数。接下来每个字符串占一行,字符串长度不超过 100,且不包含空格。

Output
每个字符串的检测结果占一行,如果该字符串可以获得“答案正确”,则输出 YES,否则输出 NO。

Sample Input

8
PAT
PAAT
AAPATAA
AAPAATAAAA
xPATx
PT
Whatever
APAAATAA

Sample Output

YES
YES
YES
YES
NO
NO
NO
NO

参考程序:

def FullChar(string,char):
	for i in string:
        if i!=char:
            return False
    return True
        

n=int(input())
for k in range(n):
    test=input()

    CharSet=set()
    StandardSet={'P','A','T'}
    for i in test:
        CharSet.add(i)
    if CharSet==StandardSet:#可以保证字符串含且仅含P/A/T三个字符
        P_index=test.index("P")
        left=test[0:P_index]
        if len(left)==0:
            if test[0]=="P" and test[-1]=="T" and FullChar(test[1:len(test)-1],"A"):
                print("YES")
            else:
                print("NO")
        else:
            if FullChar(left,"A"):
                T_index=test.index("T")
                right=test[T_index+1:]
                if FullChar(right,"A"):
                    #格式为a*'A',(1+n)*'A',(c+n)*'A' 其中a=c.
                    middleA=T_index-P_index-1
                    if (middleA-1)*len(left)==len(right)-len(left):
                        print("YES")
                    else:
                        print("NO")
                else:
                    print("NO")
            else:
                print("NO")
    else:
        print("NO")

分析:本题是PAT (Basic Level) 1003“ 我要通过!”。属于字符串处理的题目。这里边的难点主要在于题目的理解上,本人做这道题的时候,也懵圈了好久。下面我们来一起分析一下。从题目所述“答案正确”的三点要求入手:

  • 条件1说明,此字符串必须包含P/A/T三种字符,且只能包含这三种,缺少字母种类、过多类的字母、小写字母等都是不合法的。这一点我想大家都能理解,也容易设计实现。上面的程序中,使用一个集合来处理字符串,相当于“去重”
  • 条件2说明,形如 xPATx
    的字符串是“答案正确的”。如果说条件1是在整体上介绍了“答案正确”字符串应具有的最基本的特征,那么条件2就是说明了“答案正确”字符串的本源所在。这里可以举出两个典型例子:PAT (对应于x为空字符),AAPATAA(对应于x为三个A构成的字符串)。请记住这两个例子,它将作为母版,其他所谓“正确字符”必然是这种字符串的变形。
  • 条件3说明,将一个已判定为“答案正确”的字符串,施以某种变换得到的字符串也是正确的。这里包含两层含义:①在条件2举出的两个基本例子,进行变换后,是“答案正确的”,例如PAT
    → PAAT(a=’’,b=‘A’,c=’’),即PAAT“答案正确”。又如AAPATAA →
    AAPAATAAAA(a=‘AA’,b=‘A’,c=‘AA’)。②在①的基础上再次施以该变换。也是“答案正确的”,如PAAT→
    PAAAT,AAPAATAAAA→ AAPAAATAAAAAA。

因此,可以看出,对于“答案正确”的定义属于一种递推式的定义;而且无论怎么变换,任何字符串必然来自于xPATx;
所以就是,我们从xPATx入手,即可找到规律。
规律总结如下:

  • ①若x为空,则PA…A(不少于一个A)T是“答案正确的”
  • ②若x不为空,那么对于aPbTc,为了叙述方便,不妨把a,b,c看做A的个数,那么变换n次,P左边的式子应变成a个‘A’,也就是不论怎么变换,左边部分子串永远是不变的,这给我们提供了一个重要信息——个数a是几。中间应变成(b+n)个‘A’,且根据条件2,b最初是1.这也能给出个数a是几。右边的部分变成(c+a*n)个‘A’,且根据条件2,最初c和a是相等的。

本题程序主要基于遍历(一个个统计)。其实还可以借助正则表达式来实现,例如,使用“至少出现零次、一次”通配符,设计匹配模式:r’A*PA+TA*'可以一下子去掉形如PAPAT,APATPATA,PTA,这类的,剩下的再统计个数加以判断,代码会更加简洁。

运用了正则表达式的改进版程序如下:

import re
pat=re.compile(r'A*PA+TA*',flags=0)
n=int(input())
for k in range(n):
    test=input()
    if re.match(pat,test):
        P_index=test.index("P")
        left=test[0:P_index]
        if len(left)==0:
            print("YES")
        else:
            T_index=test.index("T")
            right=test[T_index+1:]
            middleA=T_index-P_index-1
            if (middleA-1)*len(left)==len(right)-len(left):
                print("YES")
            else:
                print("NO")
    else:
        print("NO")

注意:上述代码的匹配模式不能是r’(A*)PA+T\1’,\1表示引用第一个分组,即要求这个位置和第一个分组完全相同才ok,在这种模式下,必须要求a,c相同。事实上a,c不同也可能是“答案正确”的,比如AAPAAATAAAAAA。
下面是验证匹配模式正确性的例子。

import re
pat=re.compile(r'A*PA+TA*',flags=0)
ls=['AAAAAPAAAATAA','PAT','AAAPAT','APTA','AAPATAA']
for st in ls:
    if re.match(pat,st):
        print(st+"匹配成功")
    else:
        print(st+"匹配失败")

运行结果:
在这里插入图片描述
将匹配模式改为

pat=re.compile(r'(A*)PA+T\1',flags=0)

运行结果:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值