题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=2222
题意
给定多个模式串和一个主串,求有多少个模式串出现在了主串中。
思路
AC自动机模板题
代码
#define push_back pb
#define make_pair mk
#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<cmath>
#include<map>
#include<algorithm>
#include<string>
#include<string.h>
#include<set>
#include<queue>
#include<stack>
#include<functional>
using std::pair;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>PII;
const double PI=acos(-1);
const int maxn = 5e5 + 10;
const int INF = 0x3f3f3f3f;
const int md =1e9+7;
const ll inf =1e18;
using namespace std;
struct trie
{
int next[maxn][26],fail[maxn],end[maxn];
int rt,l;
int newnode()
{
for(int i=0;i<26;i++) next[l][i]=-1;
end[l++]=0;
return l-1;
}
void init()
{
l=0;
rt=newnode();
}
void insert(char *buf)
{
int len=strlen(buf);
int now=rt;
for(int i=0;i<len;i++)
{
int x=buf[i]-'a';
if(next[now][x]==-1) next[now][x]=newnode();
now=next[now][x];
}
end[now]++;
}
void build()
{
queue<int>que;
fail[rt]=rt;
for(int i=0;i<26;i++)
{
if(next[rt][i]==-1)
{
next[rt][i]=rt;
}
else
{
fail[next[rt][i]]=rt;
que.push(next[rt][i]);
}
}
while(!que.empty())
{
int now=que.front();que.pop();
for(int i=0;i<26;i++)
{
if(next[now][i]==-1) next[now][i]=next[fail[now]][i];
else
{
fail[next[now][i]]=next[fail[now]][i];
que.push(next[now][i]);
}
}
}
}
int query(char *buf)
{
int len=strlen(buf);
int now=rt;
int res=0;
for(int i=0;i<len;i++)
{
int x=buf[i]-'a';
now=next[now][x];
int temp=now;
while(temp!=rt)
{
res+=end[temp];
end[temp]=0;
temp=fail[temp];
}
}
return res;
}
};
char buf[maxn*2];
trie ac;
int main()
{
int t;
int n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
ac.init();
for(int i=0;i<n;i++)
{
scanf("%s",buf);
ac.insert(buf);
}
ac.build();
scanf("%s",buf);
printf("%d\n",ac.query(buf));
}
}