博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

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

题目链接:简单版增强版

简单版:

#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;
}
posted @ 2018-03-08 19:10  SovietPower  阅读(235)  评论(0编辑  收藏  举报