由于题目要求找的是有多少字符串包含这个目标字符串,所以我们要将每个源字符串的每一个后缀都插入到trie中,且由于一个源中可能包含多个目标,我们在插入同一个源的各个后缀时,要避免重复统计,这里可以给节点加上一个参数,标志前节点是哪个源的后缀:
#include <cstdio>
struct Node{
int id;
int cnt;
Node* children[26];
} arr[2100000] = {0};
Node* newNode()
{
static int i = 0;
return &arr[i++];
}
void insertTrie(Node* p, const char* s, int id)
{
for(; *s; ++s){
Node*& q = p->children[*s - 'a'];
if(!q) q = newNode();
if(q->id != id){
++(q->cnt);
q->id = id;
}
p = q;
}
}
int findTrie(Node* p, const char* s)
{
for(; p && *s; ++s){
Node* q = p->children[*s - 'a'];
if(!s[1]) return q != NULL ? q->cnt : 0;
p = q;
}
return 0;
}
Node root = {0};
int main()
{
int P, Q;
char s[21], *t;
Node *pTrie = &root;
scanf("%d", &P);
while(getchar() != '\n') ;
while(P--){
gets(s);
for(t = s; *t; ++t) insertTrie(pTrie, t, P + 1);
}
scanf("%d", &Q);
while(getchar() != '\n') ;
while(Q--){
gets(s);
printf("%d\n", findTrie(pTrie, s));
}
return 0;
}