洛谷.3808/3796.[模板]AC自动机

时间:2024-08-28 11:35:26

题目链接:简单版增强版

简单版:

#include <cstdio>
#include <cstring>
const int N=1e6+5,S=26; char s[N];
struct AC_Automaton
{
int cnt,q[N],val[N],fail[N],las[N],son[N][S];
// struct Node
// {
// int val,las,fail,son[S];
// Node *son[S];//指针太麻烦了。。
// Node() {val=las=0, memset(son,0,sizeof son);}
// }pool[N];
void Insert(char *s)
{
int l=strlen(s),u=0;
for(int v,i=0; i<l; ++i)
{
v=s[i]-'a';
if(!son[u][v]) son[u][v]=++cnt;
u=son[u][v];
}
++val[u];
}
void Build()
{
int h=0,t=0;
for(int i=0; i<S; ++i)
if(son[0][i]) fail[son[0][i]]=0,q[t++]=son[0][i];
while(h<t)
{
int x=q[h++];
for(int v,i=0; i<S; ++i)
if(son[x][i])
fail[v=son[x][i]]=son[fail[x]][i], q[t++]=v, las[v]=val[fail[v]]?fail[v]:las[fail[v]];
else son[x][i]=son[fail[x]][i];
}
}
int Query(char *s)
{
int l=strlen(s),res=0,u=0;
for(int i=0; i<l; ++i)
{
u=son[u][s[i]-'a'];
for(int p=u; p&&~val[p]; p=las[p])
res+=val[p], val[p]=-1;
}
return res;
}
}ac; int main()
{
int n; scanf("%d",&n);
while(n--) scanf("%s",s), ac.Insert(s);
ac.Build();
scanf("%s",s), printf("%d",ac.Query(s));
return 0;
}

增强版:1920ms(1268ms) 我说怎么慢。。数组开太大了

#include <cstdio>
#include <cstring>
#include <algorithm>
const int N=10505,S=26; int n;
char s[155][75],p[1000005];
struct AC_Automaton
{
int cnt,q[N],val[N],fail[N],las[N],son[N][S],tm[155];
void Init()
{
cnt=0, memset(son,0,sizeof son), memset(val,0,sizeof val);
}
void Insert(char *s,int id)
{
int l=strlen(s),u=0;
for(int v,i=0; i<l; ++i)
{
v=s[i]-'a';
if(!son[u][v]) son[u][v]=++cnt;
u=son[u][v];
}
val[u]=id;
}
void Build()
{
int h=0,t=0;
for(int i=0; i<S; ++i)
if(son[0][i]) fail[son[0][i]]=0,q[t++]=son[0][i];
while(h<t)
{
int x=q[h++];
for(int v,i=0; i<S; ++i)
if(son[x][i])
fail[v=son[x][i]]=son[fail[x]][i], q[t++]=v, las[v]=val[fail[v]]?fail[v]:las[fail[v]];
else son[x][i]=son[fail[x]][i];
}
}
void Query(char *p)
{
memset(tm,0,sizeof tm);
int l=strlen(p),u=0,res=0;
for(int i=0; i<l; ++i)
{
u=son[u][p[i]-'a'];
for(int p=u; p; p=las[p])
++tm[val[p]];
}
for(int i=1; i<=n; ++i) res=std::max(res,tm[i]);
printf("%d\n",res);
for(int i=1; i<=n; ++i)
if(tm[i]==res) printf("%s\n",s[i]);
}
}ac; int main()
{
while(scanf("%d",&n),n)
{
ac.Init();
for(int i=1; i<=n; ++i) scanf("%s",s[i]), ac.Insert(s[i],i);
ac.Build();
scanf("%s",p), ac.Query(p);
}
return 0;
}

增强版 第二次写(2018.4.5):1700ms(1204ms)

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
const int N=152*72,S=26; int n;
char s[152][72],p[1000005]; struct AC_Automaton
{
int tot,son[N][27],fail[N],val[N],las[N],q[N],tm[152];
void Init(){
tot=0, memset(son,0,sizeof son), memset(val,0,sizeof val);
}
void Insert(char *s,int pos)
{
int l=strlen(s),x=0;
for(int id,i=0; i<l; ++i)
{
id=s[i]-'a';
if(!son[x][id]) son[x][id]=++tot;
x=son[x][id];
}
val[x]=pos;
}
void Build()
{
int h=0,t=0;
for(int i=0; i<S; ++i)
if(son[0][i]) fail[son[0][i]]=0,q[t++]=son[0][i];
while(h<t)
{
int x=q[h++];
for(int v,i=0; i<S; ++i)
if(son[x][i])
fail[v=son[x][i]]=son[fail[x]][i],q[t++]=v,las[v]=val[fail[v]]?fail[v]:las[fail[v]];
else son[x][i]=son[fail[x]][i];
}
}
void Query(char *p)
{
int l=strlen(p),res=0,x=0;
memset(tm,0,sizeof tm);
for(int i=0; i<l; ++i)
{
x=son[x][p[i]-'a'];
for(int j=x; j; j=las[j]) ++tm[val[j]];
}
for(int i=1; i<=n; ++i) if(res<tm[i]) res=tm[i];
printf("%d\n",res);
for(int i=1; i<=n; ++i) if(tm[i]==res) printf("%s\n",s[i]);
}
}ac; int main()
{
while(scanf("%d",&n),n){
ac.Init();
for(int i=1; i<=n; ++i) scanf("%s",s[i]),ac.Insert(s[i],i);
ac.Build(), scanf("%s",p), ac.Query(p);
}
return 0;
}