题意: 给出一些关键词,求在下面的字符串中出现的有多少个
分析:AC自动机模板题
注意:1.关键词可能在字符串中出现多次,只算一次
2.关键词可能相同,都要算
3.用数组写会卡内存,开250000差不多能卡过
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<queue>
using namespace std;
char str[1000005];
struct Tire{
Tire *child[26];
Tire *fail;
int cnt;
Tire(){
cnt=0;
fail=0;
memset(child,0,sizeof(child));
}
};
int idx(char c){
return c-'a';
}
void insert(char *s,Tire *root){
Tire *p=root;
int n=strlen(s);
for(int i=0;i<n;i++){
int v=idx(s[i]);
if(p->child[v]==0){
p->child[v]=new Tire;
}
p=p->child[v];
}
p->cnt++;
}
void getFail(Tire *root){
Tire *front;
queue<Tire *> q;
q.push(root);
while(!q.empty()){
front=q.front();
q.pop();
for(int i=0;i<26;i++){
if(front->child[i]!=NULL){
if(front==root)
front->child[i]->fail=root;
else {
Tire *tmp=front;
while(tmp->fail!=NULL){
if(tmp->fail->child[i]!=NULL){
front->child[i]->fail=tmp->fail->child[i];
break;
}
tmp=tmp->fail;
}
if(tmp->fail==NULL)
front->child[i]->fail=root;
}
q.push(front->child[i]);
}
}
}
}
int find(char *T,Tire *root){
int n=strlen(T);
Tire *p=root;
Tire *tmp=NULL;
int k,ans=0;
for(int i=0;i<n;i++){
k=idx(T[i]);
while(p!=root&&p->child[k]==NULL){
p=p->fail;
}
if(p->child[k]!=NULL){
p=p->child[k];
tmp=p;
while(tmp!=root){
ans+=tmp->cnt;
tmp->cnt=0;
tmp=tmp->fail;
}
}
}
return ans;
}
int main()
{
int t,n;
scanf("%d",&t);
while(t--){
Tire *root=new Tire;
scanf("%d",&n);
while(n--){
scanf("%s",str);
insert(str,root);
}
scanf("%s",str);
getFail(root);
printf("%d\n",find(str,root));
}
return 0;
}