ITSA 基礎題庫 —— 題目17. 英文斷詞

題目 Problem

題目連結:https://e-tutor.itsa.org.tw/e-Tutor/mod/programming/view.php?a=15924

敘述 Description

斷詞在自然語言的研究上是個很重要的步驟,主要就是將關鍵字從句子中斷出,英文的斷詞較為簡單,就根據句子中的空格將英文字隔開。

輸入 Input

輸入一句英文敘述句。 字元數 $\leq 1000$。

輸出 Output

將輸入的句子進行斷詞,將斷出的關鍵字依照句子中的出現排序列印出。全部轉成小寫,列印出的關鍵字不得重複,關鍵字間以一個空格隔開,最後一個關鍵字後面進行換行。例如輸入 How do you do ,則輸出 how do you 。

範例輸入 Sample Input

1
How do you do

範例輸出 Sample Output

1
how do you

提示 Hint

題解 Solution

C++ 題解程式還蠻多的,我來寫個 C 語言能解開的版本

C 語言可以使用 string.h String Token (strtok) 去解決
我們來看 strtok 函式原型

1
char* strtok( char* str, const char* delim );

引數傳要切割的字串 str、切割的關鍵字元 delim

回傳的是字元指標,就是位於切割字元之間的字串
如果拿到 NULL 就代表已經沒了

但是,如果想再搜尋同一句話的下一個切割字元之間字串,str 就傳 NULL 即可

通常我會搭配 while 迴圈去完成

這題要先把所有字串轉為小寫
第一次做 strtok 的時候要 str 引數傳需要被切割的字串
第二次以後 str 引數直接傳 NULL
直到回傳值為 NULL 跳出迴圈

while 迴圈裡,需要搜尋這個字串是否存在

搭配 strcmp 去完成

不存在則於迴圈的最後 strcpy 進去

最後再列出所有字串

程式碼 Accepted Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include<stdio.h>  
#include<string.h>
#include<ctype.h>
int main() {
char enter[10000];
fgets(enter, 9999, stdin);
int len = strlen(enter);
for (int i = 0 ; i < len; i++) {
enter[i] = tolower(enter[i]);
}
char ans[1000][1000];
int nowAns = 0;
char *pch = strtok(enter, " \r\n"); // 爛坑!!!
while(pch != NULL) {
int judge = 1;
for (int i = 0; i < nowAns; i++) {
if (strcmp(ans[i], pch) == 0) {
judge = 0;
break;
}
}
if (judge) {
strcpy(ans[nowAns], pch);
nowAns++;
}
pch = strtok(NULL, " \r\n"); // 爛坑!!!
}
for (int i = 0; i < nowAns; i++) {
if(i)
printf(" ");
printf("%s", ans[i]);
}
printf("\n");
return 0;
}

後記 Afterword

Line 13 / 26 我寫了一個註解叫做爛坑!!

一開始寫了的 Token 如果只有空格跟換行(沒有 \r
會直接吃兩個 AC、兩個 WA,根本不知道問題在哪
\r 我就直接順手加進去,就 AC

理當來說換行為 \n
但 Windows 換行為 \r\n
我覺得測試資料可能有些是 Windows 手動產生

之前有個月賽題目賽後的測資有錯
歷史紀錄沒有人 AC 那題(放題目的人不會覺得詭異嗎?)
E-mail 反應後也是音訊全無

FB 社團裡的人也說這個平台實在是不敢領教
這篇特別紀錄一下很坑的通靈之路


ITSA 基礎題庫 —— 題目17. 英文斷詞
https://blog.yangjerry.tw/2020/06/01/itsa-basic-17/
作者
Jerry Yang
發布於
2020年6月1日
許可協議