查询单词是否存在于上面的所有单词中,输出存在的单词数。
因为数量很大啊,所以不能枚举,然后就想到字典树了。但是肯定不能建一棵,因为查询的单词可能是从中间开始的。
所以就枚举单词的每个字母作为起点,剩下的去建树,每个字母建成一棵树,这样的话,查找的代价就是单词的长度。
不过内存需要开很大,MLE了数次= = 。。。好久没写字典树了。。。还算顺利吧。
#include <queue> #include <stack> #include <math.h> #include <stdio.h> #include <stdlib.h> #include <iostream> #include <limits.h> #include <string.h> #include <string> #include <algorithm> using namespace std; const int MAX = 10001*50; typedef struct NODE{ int cnt,ind; NODE *next[26]; }NODE; NODE *a[26],node[MAX]; int cou; void init() { memset(node,0,sizeof(node)); cou = 27; for(int i=0; i<26; i++) a[i] = &node[i]; } void Add(char *s,int n,int ind) { NODE *head = a[s[0]-'a']; if( head->ind != ind ) { head->cnt++; head->ind = ind; } for(int i=1; i<n; i++) { if( head->next[s[i]-'a'] == NULL) { head->next[s[i]-'a'] = &node[cou++]; head->next[s[i]-'a']->cnt = 0; head->next[s[i]-'a']->ind = 0; } head = head->next[s[i]-'a']; if( head->ind != ind ) { head->cnt++; head->ind = ind; } } } int find(char *s,int n) { NODE *head = a[s[0]-'a']; for(int i=1; i<n; i++) { if( head->next[s[i]-'a'] != NULL ) head = head->next[s[i]-'a']; else return 0; } return head->cnt; } int main() { int n,q; char str[50]; while( ~scanf("%d",&n) ) { init(); for(int i=1; i<=n; i++) { scanf("%s",str); int len = strlen(str); for(int k=0; k<len; k++) Add(str+k,len-k,i); } scanf("%d",&q); while( q-- ) { scanf("%s",str); int ans = find(str,strlen(str)); printf("%d\n",ans); } } return 0; }