查询单词是否存在于上面的所有单词中,输出存在的单词数。
因为数量很大啊,所以不能枚举,然后就想到字典树了。但是肯定不能建一棵,因为查询的单词可能是从中间开始的。
所以就枚举单词的每个字母作为起点,剩下的去建树,每个字母建成一棵树,这样的话,查找的代价就是单词的长度。
不过内存需要开很大,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;
}