1. 程式人生 > 其它 >Python程式設計基礎題(21-我要通過!)

Python程式設計基礎題(21-我要通過!)

技術標籤:Python語言程式設計

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)

執行結果:
在這裡插入圖片描述