今天想跟大家分享 **a224. 明明愛明明** 這一題我的解題想法,有任何想討論的歡迎提出喔
### 以下是我的程式碼
```
#include<bits/stdc++.h>
using namespace std;
int main(){
string s;
while(getline(cin,s)){
//change to small alpha
for(int i=0;i<s.size();i++){
if(isalpha(s[i])){
s[i]=tolower(s[i]);
}
}
sort(s.begin(),s.end());
//delete : ; , _
for(int i=0;i<s.size();i++){
if(!isalpha(s[0])){
s.erase(0,1);
}
}
int odd=0;
char nowchar=s[0];
int time=0;
for(int i=0;i<s.size();i++){
if(isalpha(s[i])){
if(nowchar==s[i]){
time++;
}
else if(nowchar!=s[i]){
if(time%2==1) odd+=1;
time=1;
nowchar=s[i];
}
}
}
if (time % 2 == 1) odd++;
//output
if(odd<=1) cout<<"yes !"<<endl;
else cout<<"no..."<<endl;
}
}
```
---
### 講解~
1. 第一部分
```
while(getline(cin,s)){
//change to small alpha
for(int i=0;i<s.size();i++){
if(isalpha(s[i])){
s[i]=tolower(s[i]);
}
}
```
這裡我用getline直接取得字串
藉著我用迴圈把字元一個一個取出來做比較
我利用了**isalpha()函式**來判斷該字元是不是字母,如果是就一律轉成小寫英文字母
再來我用了 **sort(s.begin(),s.end())的函式**把字串s排序,排完後我發現那些標點符號 : ; , _ 都被擺到了前面。
---
2. 第二部分
基於剛剛的觀察結果,我用了**erase()函式**,我從頭開始一個一個刪除那些標點符號,
```
//delete : ; , _
for(int i=0;i<s.size();i++){
if(!isalpha(s[0])){
s.erase(0,1);
}
}
```
現在可以試試看把s印出來,應該會是一個照順序排好,只有小寫英文字的字串
接著我們可以來做下一步處理了!
補充:我後來問了GPT 他給出了另一個方式
```
// 刪除所有非字母字元
for (int i = 0; i < s.size(); ) {
if (!isalpha(s[i])) {
s.erase(i, 1);
} else {
i++;
}
}
```
這裡大家就看看喜歡用哪一種方式啦,不過我的方式有可能漏掉其他不是在開頭的非字母,或者無限迴圈。
---
3. 第三部分
```
int odd=0;
char nowchar=s[0];
int time=0;
for(int i=0;i<s.size();i++){
if(isalpha(s[i])){
if(nowchar==s[i]){
time++;
}
else if(nowchar!=s[i]){
if(time%2==1) odd+=1;
time=1;
nowchar=s[i];
}
}
}
if (time % 2 == 1) odd++;
```
因為剛剛都把字元排好了,所以我現在的想法:我從頭開始跑,當輪到那個字元,看看跟上一個字元是不是相同的,如果相同,就把次數time加上一(代表那個字元出現的次數多一次),如果不同,那就觸發換字,開始結算目前的time,判斷該字元總共出現的次數,如果是基數,那就把odd 加上一。
至於這部分最後一行的**if (time % 2 == 1) odd++;**是因為迴圈都跑完,但是最後一部分的time還沒有結算,所以這裡要讓他直接結算
---
4. 第四部份
```
//output
if(odd<=1) cout<<"yes !"<<endl;
else cout<<"no..."<<endl;
```
這邊說一下我對回文的理解,剛剛上一步,我們已經算出有幾個字元是出現過**基數次**
接著我們想一下:
1. 假設現在是aabbcc 沒有字元出現基數次 可以組成acbbca
2. 假設現在是aabbbcc 只有一個字元b出現基數次 可以組成acbbbca
3. 假設現在是aabbbccc 有兩個字元出現基數次 不能組成回文
所以我們依據剛剛算出的odd,如果odd<=1才是可以組成回文的
最後再把答案輸出就大功告成啦~