題目
“答案正確” 是自動判題系統給出的最令人歡喜的回覆。本題屬於 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
思路分析
這題我想複雜了,看到條件二 xPATx 不自覺想到正規表示式的反向引用,但是條件三用正則比較複雜,雖然此題 AC 了,但是做的實在是很不漂亮,以後有時間還得重新研究一下。
條件1,2都非常簡單
條件3要難點在於條件是遞迴式的,簡單計算易得, a * b = c
c++ 應該使用 "." 保證轉義,如 .1
正則搜尋迭代器 regex_search()
注意不能用 "A*" 等無底線要求,會無限迭代
最後輸出注意空行 \n
舉一反三
正則雖好,其侷限性也要在考慮範圍內
推薦一本正規表示式的閱讀書籍,我已經看完了,寫的非常好:
精通正規表示式
我這邊有影印版,想要的朋友也可以聯絡我
程式碼
#include <iostream>
#include <regex>
/*注意事項:
* 條件1,2都非常簡單
* 條件3要難點在於條件是遞迴式的,簡單計算易得, a * b = c
* c++ 應該使用 "\\" 保證轉義,如 "\\1"
* 正則迭代器注意不能用 "A*" 等無底線要求,會無限迭代
* 最後輸出注意空行 "\n"
* */
using namespace std;
int num = 0;
string str;
regex regex_1("[P|A|T]+");//滿足條件一
regex regex_2("(A*)PAT\\1");//滿足條件二直接輸出
regex regex_3("A*PA+TA*");//條件三的大前提
regex regex_4("A+");//找到 A 的數量
bool checkString(string str) {
int i = 0;
bool r1, r2, r3, r4;
smatch result;
string temp[3];
string::const_iterator iterStart = str.begin();
string::const_iterator iterEnd = str.end();
r1 = regex_match(str, regex_1);
r2 = regex_match(str, regex_2);
r3 = regex_match(str, regex_3);
//使用迭代器,將正則匹配到的結果存在 temp[] 裡
while (regex_search(iterStart, iterEnd, result, regex_4)) {
temp[i++] = result[0];
iterStart = result[0].second;
}
//滿足 a * b = c
r4 = ((temp[0].size() * temp[1].size() == temp[2].size()));
//r1 必須滿足,r2 或 r3 && r4 滿足即可
if (r1 && (r2 || (r3 && r4))) {
return true;
} else return false;
}
int main() {
cin >> num;
string arr[num];
for (int i = 0; i < num; i++) {
cin >> str;
if (checkString(str)) {
arr[i] = "YES";
} else arr[i] = "NO";
}
for (int i = 0; i < num; i++) {
cout << arr[i] << "\n";
}
return 0;
}