hdu_1251统计难题(字典树Trie)
统计难题
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131070/65535 K (Java/Others)
Total Submission(s): 31479 Accepted Submission(s): 12087
Problem Description
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
Input
输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.
注意:本题只有一组测试数据,处理到文件结束.
注意:本题只有一组测试数据,处理到文件结束.
Output
对于每个提问,给出以该字符串为前缀的单词的数量.
Sample Input
banana
band
bee
absolute
acm
ba
b
band
abc
Sample Output
2 3 1 0
字典树的典型应用,主要要会写建树和查找树的过程。遍树的时候要用dfs 我发现用指针写树很好写,所以就用指针了,哈哈
下面是代码,字典树可以保存成模板,
这个题让我长知识的是对于输入输出的限制,还有c++和G++对内存管理的机智不太一样,这个题就是用G++交的时候回抄内存,用c++交就过了
然后输入的时候总结一下:
因为是scanf("%d",&tm) 是不会读入最后的回车的,而scanf("%c“,&ch)会读回车,所以在%d后面要是回车再读入%c的话要加getchar()
scanf("%s",Str)是不会读入回车的,它会自动忽略回车,且到回车停止。
所以如果输入需要读入回车的话需要用gets();
这个题还可以用set的方法过掉,因为字符串不超过10所以可以直接就把每个字符串的所有前缀放到set里然后再处理
字典树方法:
1 #include <cstdio> 2 #include <cstring> 3 #include <malloc.h> 4 #include <iostream> 5 using namespace std; 6 #define MAXN 26 7 typedef struct Trie { 8 int v;//根据需要变化 9 Trie *next[MAXN]; 10 //next是表示每层有多少种类的数,如果只是小写字母,则26即可, 11 //若改为大小写字母,则是52,若再加上数字,则是62了 12 } Trie; 13 Trie root; 14 15 void createTrie(char *str) { 16 int len = strlen(str); 17 Trie *p = &root, *q; 18 for(int i = 0; i < len; i++) { 19 int id = str[i]-'a'; 20 if(p->next[id] == NULL) { 21 q = (Trie *)malloc(sizeof(root)); 22 q->v = 1;//初始v==1 23 for(int j = 0; j < MAXN; j++) 24 q->next[j] = NULL; 25 p->next[id] = q; 26 p = p->next[id]; 27 } else { 28 p->next[id]->v++; 29 p = p->next[id]; 30 } 31 } 32 // p->v = -1;//若为结尾,则将v改成-1表示 33 } 34 35 int findTrie(char *str) { 36 int len = strlen(str); 37 Trie *p = &root; 38 for(int i = 0; i < len; i++) { 39 int id = str[i]-'a'; 40 p = p->next[id]; 41 if(p == NULL) //若为空集,表示不存以此为前缀的串 42 return 0; 43 // if(p->v == -1) //字符集中已有串是此串的前缀 44 // return -1; 45 } 46 return p->v; 47 //return -1; //此串是字符集中某串的前缀 48 } 49 int dealTrie(Trie* T) { 50 //动态字典树,有时会超内存,这是就要记得释放空间了 51 if(T==NULL) 52 return 0; 53 for(int i = 0; i < MAXN; i++) { 54 if(T->next[i]!=NULL) 55 dealTrie(T->next[i]); 56 } 57 free(T); 58 return 0; 59 } 60 int main() { 61 char str[15]; 62 for(int i = 0; i < MAXN; i++) 63 root.next[i] = NULL; 64 while(gets(str) && str[0]!='\0') 65 createTrie(str); 66 memset(str, 0, sizeof(str)); 67 while(scanf("%s", str) != EOF) { 68 int ans = findTrie(str); 69 printf("%d\n", ans); 70 } 71 return 0; 72 }
set方法:
1 #include <cstdio> 2 #include <iostream> 3 #include <map> 4 #include <cstring> 5 #include <string> 6 using namespace std; 7 8 int main() 9 { 10 char str[17]; 11 map<string, int> m; 12 while(gets(str)) 13 { 14 int len = strlen(str); 15 if (!len) 16 { 17 break; 18 } 19 for(int i = len; i > 0; i--) 20 { 21 str[i] = '\0'; 22 m[str]++; 23 } 24 } 25 while(gets(str)) 26 { 27 cout<<m[str]<<endl; 28 } 29 30 return 0; 31 }