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一次预处理,查询即可。
代码如下:
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> using namespace std; typedef struct node { node *next[26]; node *fail; int sum; }node; const int maxn = 10000 + 5; char s[maxn]; node *root; void Insert() { int len = strlen(s); node *p = root; for(int i = 0;i < len; ++i) { int x = s[i] - 'a'; if(p->next[x] == NULL) { p->next[x] = (node *)malloc(sizeof(node)); p->next[x]->fail = NULL; for(int j = 0;j < 26; ++j) p->next[x]->next[j] = NULL; p->next[x]->sum = 0; } p = p->next[x]; } p->sum++; } int cal(node *x) { if(!x) return 0; int ans = 0; for(int i = 0;i < 26; ++i) { ans += cal(x->next[i]); } x->sum += ans; return x->sum; } int Find() { int len = strlen(s); node *p = root; for(int i = 0;i < len; ++i) { int x = s[i] - 'a'; if(p->next[x] == NULL) return 0; p = p->next[x]; } return p->sum; } int main() { root = (node *)malloc(sizeof(node)); for(int i = 0;i < 26; ++i) root->next[i] = NULL; root->fail = NULL; root->sum = 0; while(gets(s)) { if(s[0] == '\0') break; Insert(); } cal(root); while(scanf("%s",s) != EOF) { printf("%d\n",Find()); } return 0; }