题目大意:有T组数据,每组数据中有n个模式串,给出一个主串,求出在主串中有多少个模式串出现过
AC自动机裸题。
AC自动机就是在Trie上做KMP,处理出在某位置失配后应该跳到什么位置,然后正常查询即可。
需要注意的是,还要处理一下不断地跳fail遇到第一个单词在什么位置,统计答案时也要统计一下。
板子在这里。
#include <cstdio>
#include <cstring>
#include <queue>
#define N 1000005
using namespace std;
struct Node {
Node *ch[26],*nxt;
int val;
bool jud;
Node():nxt(NULL),val(0),jud(false) { for(int i=0;i<26;i++) ch[i]=NULL; }
}*root;
int n;
char s[N];
void Insert() {
Node* o=root;
int len=strlen(s);
for(int i=0;i<len;i++) {
int z=s[i]-'a';
if(o->ch[z]==NULL) o->ch[z]=new Node();
o=o->ch[z];
}
o->val++;
return ;
}
void getFail() {
queue<Node*> q;
Node *o=root;
for(int i=0;i<26;i++)
if(o->ch[i]!=NULL) q.push(o->ch[i]) , o->ch[i]->nxt=o;
else o->ch[i]=o;
while(!q.empty()) {
o=q.front(); q.pop();
for(int i=0;i<26;i++)
if(o->ch[i]!=NULL) q.push(o->ch[i]) , o->ch[i]->nxt=o->nxt->ch[i];
else o->ch[i]=o->nxt->ch[i];
Node *tmp=o;
tmp=tmp->nxt;
while(tmp!=root && !tmp->val) tmp=tmp->nxt;
o->nxt=tmp;
}
return ;
}
int ans;
void Match() {
ans=0;
Node *o=root;
int len=strlen(s);
for(int i=0;i<len;i++) {
int z=s[i]-'a';
o=o->ch[z];
Node *tmp=o;
while(tmp!=root && !tmp->jud) {
ans+=tmp->val , tmp->jud=true;
tmp=tmp->nxt;
}
}
return ;
}
int main() {
int T;
scanf("%d",&T);
while(T--) {
root=new Node();
scanf("%d",&n);
while(n--) scanf("%s",s) , Insert();
getFail();
scanf("%s",s);
Match();
printf("%d\n",ans);
}
return 0;
}