1. 给出模式串和文本串,文本串长度小于1e6,模式串长度之和小于1e6,求文本串中有多少模式串出现。
题目链接:https://www.luogu.org/problem/P3808
AC code:
/*
luoguP3808 (AC自动机模板题)
求文本串中有多少模式串出现
*/
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
const int maxn=1e6+5;
struct Tree{ //Trie树
int fail,vis[30],key; //key用来记录有几个单词以这个节点结尾
}AC[maxn];
int n,cnt;
char s[maxn];
//在Trie树中插入结点
void build(char *s){
int len=strlen(s),u=0;
for(int i=0;i<len;++i){
int t=s[i]-'a';
if(!AC[u].vis[t])
AC[u].vis[t]=++cnt;
u=AC[u].vis[t];
}
AC[u].key+=1;
}
//构建fail指针
void get_fail(){
queue<int> que;
for(int i=0;i<26;++i){ //提前处理第二层
if(AC[0].vis[i]){
AC[AC[0].vis[i]].fail=0; //指向根节点
que.push(AC[0].vis[i]);
}
}
while(!que.empty()){ //bfs求所有子结点
int u=que.front();
que.pop();
for(int i=0;i<26;++i){
if(AC[u].vis[i]){
AC[AC[u].vis[i]].fail=AC[AC[u].fail].vis[i];
que.push(AC[u].vis[i]);
}
else{
AC[u].vis[i]=AC[AC[u].fail].vis[i];
}
}
}
}
//AC自动机匹配
int query(char *s){
int len=strlen(s),u=0,ans=0;
for(int i=0;i<len;++i){
int t=s[i]-'a';
u=AC[u].vis[t];
for(int j=u;j&&AC[j].key!=-1;j=AC[j].fail){ //循环求解
ans+=AC[j].key;
AC[j].key=-1;
}
}
return ans;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%s",s);
build(s);
}
AC[0].fail=0; //结束标志
get_fail(); //求失配指针
scanf("%s",s);
printf("%d\n",query(s));
return 0;
}