HDU-1251 统计难题 (Trie)
题目:
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
Input
输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.
注意:本题只有一组测试数据,处理到文件结束.
Output
对于每个提问,给出以该字符串为前缀的单词的数量.
Sample Input
banana
band
bee
absolute
acmba
b
band
abc
Sample Output
2
3
1
0
思路:
- Trie字典树模板题,我用了两种做法,一种是指针写的,一种是汪神传授的数组模拟,数组一开始过不去问学长说数组要开大一点。
- 数组模拟Trie有一点我想了很久才明白,就是ch[1][x]只记录每个串第一个位置的下标,相当于一个入口,如果要标记或者计数是不考虑它的。
- 这题提交要用C++,G++会MLE。
链式Trie代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<set> 8 9 using namespace std; 10 11 typedef struct TrieNode{ 12 int cnt; 13 bool flag; 14 TrieNode *next[26]; 15 TrieNode(){ 16 cnt = 0; 17 flag = false; 18 memset(next, 0, sizeof(next)); 19 } 20 }TrieNode, *Trie; 21 22 TrieNode *InitTrieNode(){ 23 TrieNode *p = new TrieNode; 24 return p; 25 } 26 27 void InsertNode(Trie root, char *word){ 28 Trie p = root; 29 char *ch = word; 30 int id; 31 while(*ch){ 32 id = *ch - 'a'; 33 if (p->next[id] == NULL) 34 p->next[id] = InitTrieNode(); 35 p = p->next[id]; 36 p->cnt++; 37 ++ch; 38 } 39 p->flag = true; 40 } 41 42 int TrieSearch(Trie root, char *word){ 43 Trie p = root; 44 char *ch = word; 45 int id; 46 bool ans = false; 47 while(*ch){ 48 id = *ch - 'a'; 49 if (p->next[id] == NULL) 50 return 0; 51 p = p->next[id]; 52 ++ch; 53 } 54 return p->cnt; 55 } 56 57 int main() 58 { 59 Trie root = InitTrieNode(); 60 char ch[15], c; 61 while(gets(ch), ch[0]){ 62 InsertNode(root, ch); 63 } 64 while(scanf("%s", &ch) != EOF){ 65 printf("%d\n", TrieSearch(root, ch)); 66 } 67 68 return 0; 69 }
数组模拟Trie代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<set> 8 9 using namespace std; 10 int ch[1100000][26], cnt[1100000], fir[26], num = 1; 11 12 void Insert(char *word){ 13 int now = 1, len = strlen(word), id; 14 for (int i = 0; i < len; ++i){ 15 id = word[i] - 'a'; 16 if (ch[now][id]) now = ch[now][id]; 17 else now = ch[now][id] = ++num; 18 ++cnt[now]; 19 } 20 } 21 22 int Search(char *pre){ 23 int len = strlen(pre), now = 1, id; 24 for (int i = 0; i < len; ++i){ 25 id = pre[i] - 'a'; 26 if (ch[now][id]) now = ch[now][id]; 27 else return 0; 28 } 29 return cnt[now]; 30 } 31 32 int main() 33 { 34 char word[20], c; 35 while(gets(word), word[0]){ 36 Insert(word); 37 } 38 while(scanf("%s", &word) != EOF){ 39 printf("%d\n", Search(word)); 40 } 41 42 return 0; 43 }