统计难题
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131070/65535 K (Java/Others)
Total Submission(s): 26574 Accepted Submission(s): 10760
Problem Description
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
Input
输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.
注意:本题只有一组测试数据,处理到文件结束.
注意:本题只有一组测试数据,处理到文件结束.
Output
对于每个提问,给出以该字符串为前缀的单词的数量.
Sample Input
banana
band
bee
absolute
acm
ba
b
band
abc
Sample Output
2
3
1
0
Author
Ignatius.L
【思路】
Trie。
构建一棵字典树,并维护tot[u]表示以u为根的子数中叶子节点的数目。
需要注意的是maxnode要开大一些。
【代码】
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 5 using namespace std; 6 7 const int maxnode = 2000000; 8 //输入的字符串可能很多 9 const int maxl = 15; 10 const int sigmasize = 26; 11 12 struct Trie{ 13 int ch[maxnode][sigmasize]; 14 int tot[maxnode]; 15 int sz; 16 17 Trie() { 18 sz=1; 19 memset(ch[0],0,sizeof(ch[0])); 20 tot[0]=0; 21 } 22 int idx(char c) { return c-'a'; } 23 void insert(char* s) { 24 int n=strlen(s),u=0; 25 for(int i=0;i<n;i++) { 26 int c=idx(s[i]); 27 if(!ch[u][c]) { 28 ch[u][c]=sz; 29 memset(ch[sz],0,sizeof(ch[sz])); 30 tot[sz]=0; 31 sz++; 32 } 33 u=ch[u][c]; 34 tot[u]++; 35 } 36 } 37 int find(char* s) { 38 int n=strlen(s),u=0; 39 for(int i=0;i<n;i++) { 40 int c=idx(s[i]); 41 if(!ch[u][c]) return 0; 42 else u=ch[u][c]; 43 } 44 return tot[u]; 45 } 46 }trie; 47 48 int n; 49 50 int main() { 51 //freopen("cin.in","r",stdin); 52 //freopen("coutme.out","w",stdout); 53 char s[maxl]; 54 while(gets(s) && s[0]) { 55 trie.insert(s); 56 } 57 while(gets(s)) { 58 printf("%d ",trie.find(s)); 59 } 60 return 0; 61 }