HDU 2846 Trie查询

时间:2024-06-02 15:37:38

给出若干模式串,再给出若干询问串,求每个询问串作为多少个模式串的子串出现。

如果一个串是另一个串的子串,则一定是另一个串某个前缀的后缀或者某个后缀的前缀。根据字典树的性质,将模式串的每一个后缀插入字典树中,同时更新字典树中节点的cnt值。这里需要注意不要重复累加贡献,可以在字典树中新增一个num的信息值来实现这一点。

 #include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <string.h>
#include <stdio.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <cassert>
#include <sstream>
using namespace std; const int N=;
const int MOD=1e9+; const int CHARSET=,BASE='a',MAX_NODE=**+;
struct Trie {
int tot,root,child[MAX_NODE][CHARSET];
int flag[MAX_NODE],num[MAX_NODE];
Trie(){
init();
}
void init(){
tot=;
root=newNode();
}
int newNode() {
++tot;
memset(child[tot],,sizeof(child[tot]));
flag[tot]=;
num[tot]=-;
return tot;
}
void insert(const char *str,int id){
int *cur=&root;
for (const char *p=str;*p;++p){
cur=&child[*cur][*p-BASE];
if (*cur==){
*cur=newNode();
}
if (num[*cur]!=id)
flag[*cur]++;
num[*cur]=id;
}
}
int query(const char *str){
int *cur=&root;
for (const char *p=str;*p&&(*cur);++p){
cur=&child[*cur][*p-BASE];
}
return flag[*cur];
}
}trie;
int main () {
int n;
scanf("%d",&n);
char s[];
for (int i=;i<=n;i++) {
scanf("%s",s);
int len=strlen(s);
for (int j=;j<len;j++)
trie.insert(s+j,i);
}
int Q;
scanf("%d",&Q);
while (Q--) {
scanf("%s",s);
int ret=trie.query(s);
printf("%d\n",ret);
}
return ;
}