统计单词数 OpenJ_Bailian - 4030 (KMP)
描述
一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数。
现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给定的文章中出现的次数和第一次出现的位置。注意:匹配单词时,不区分大小写,但要求完全匹配,即给定单词必须与文章中的某一独立单词在不区分大小写的情况下完全相同 (参见样例 1) ,如果给定单词仅是文章中某一单词的一部分则不算匹配(参见样例 2) 。
输入第 1 行为一个字符串,其中只含字母,表示给定单词;
第 2 行为一个字符串,其中只可能包含字母和空格,表示给定的文章。输出只有一行, 如果在文章中找到给定单词则输出两个整数, 两个整数之间用一个空格隔开,分别是单词在文章中出现的次数和第一次出现的位置(即在文章中第一次出现时,单词首字母在文章中的位置,位置从 0 开始) ;如果单词在文章中没有出现,则直接输出一个整数-1。样例输入
样例 #1:
To
to be or not to be is a question
样例 #2:
to
Did the Ottoman Empire lose its power at that time
样例输出
样例 #1:
2 0
样例 #2:
-1
提示【输入输出样例 1 说明】
输出结果表示给定的单词 To 在文章中出现两次,第一次出现的位置为 0。
【输入输出样例 2 说明】
表示给定的单词 to 在文章中没有出现,输出整数-1。
【数据范围】
1 ≤单词长度≤10。
1 ≤文章长度≤1,000,000。
小技巧:难点在于查找单词,单词的两边必有空格,所以在单词和句子两边都加上空格,再使用kmp算法就行了。
1 #include <iostream> 2 #include <string> 3 #include <cctype> 4 5 using namespace std; 6 7 int nxt[11]; 8 9 void getNext(string p, int nxt[]) 10 { 11 int i = 0, j = -1; 12 nxt[0] = -1; 13 14 int plen = p.length(); 15 while(i < plen) 16 { 17 if(j == -1 || p[i] == p[j]) 18 { 19 ++i; 20 ++j; 21 nxt[i] = j; 22 } 23 else 24 { 25 j = nxt[j]; 26 } 27 } 28 } 29 30 int kmp(string t, string p) 31 { 32 int i = 0, j = 0; 33 34 int tlen = t.length(); 35 int plen = p.length(); 36 37 while(i < tlen && j < plen) 38 { 39 if(j == -1 || t[i] == p[j]) 40 { 41 ++i; 42 ++j; 43 } 44 else 45 { 46 j = nxt[j]; 47 } 48 } 49 50 if(j == plen) 51 return i - j; 52 else 53 return -1; 54 55 } 56 57 int main() 58 { 59 string word, sentence; 60 getline(cin, word); 61 getline(cin, sentence); 62 // 在单词和句子的首尾各加上一个空格 63 word = " " + word + " "; 64 sentence = " " + sentence + " "; 65 for(int i = 0; i < word.length(); ++i) 66 { 67 if(isupper(word[i])) 68 { 69 word[i] = tolower(word[i]); 70 } 71 } 72 for(int i = 0; i < sentence.length(); ++i) 73 { 74 if(isupper(sentence[i])) 75 { 76 sentence[i] = tolower(sentence[i]); 77 } 78 } 79 80 getNext(word, nxt); 81 int pos = kmp(sentence, word); 82 if(pos == -1) 83 { 84 cout << -1; 85 return 0; 86 } 87 88 int firstFind = pos; 89 int cnt = 0; 90 while(pos != -1) 91 { 92 cnt++; 93 // 注意:保留尾部空格 94 sentence = sentence.substr(pos+word.length()-1); 95 pos = kmp(sentence, word); 96 } 97 98 cout << cnt << ' ' << firstFind; 99 100 return 0; 101 }