AC自动机


本文共三道题目,都是 $ AC $ 自动机的模板题


初学AC自动机,AC自动机可以理解为“Trie树上KMP”(所以要先学会Trie树和KMP哦!)


1.Luogu P3808 【模板】AC自动机(简单版)

Code

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define LL long long
using namespace std;
const int N=1000005;
int n,rot,nxt[N],num[N],trie[N][26];
char pat[N],txt[N];
void insert(char s[])
{
	int u=0,len=strlen(s+1);
	for(int i=1;i<=len;i++)
	{
		int v=s[i]-'a';
		if(!trie[u][v]) trie[u][v]=++rot;
		u=trie[u][v];
	}
	num[u]++;
	return;
}
void bfs()
{
	queue<int> q;
	for(int i=0;i<26;i++) if(trie[0][i]) q.push(trie[0][i]);
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(int i=0;i<26;i++)
		{
			if(trie[u][i])
			{
				nxt[trie[u][i]]=trie[nxt[u]][i];
				q.push(trie[u][i]);
			}
			else trie[u][i]=trie[nxt[u]][i];
		}
	}
	return;
}
int find(char s[])
{
	int u=0,res=0,len=strlen(s+1);
	for(int i=1;i<=len;i++)
	{
		int v=s[i]-'a';
		for(int j=trie[u][v];j&&num[j]!=-1;j=nxt[j])
		{
			res+=num[j];
			num[j]=-1;
		}
		u=trie[u][v];
	}
	return res;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		cin>>(pat+1);
		insert(pat);
	}
	bfs();
	cin>>(txt+1);
	printf("%d\n",find(txt));
	return 0;
}


2.Luogu P3796 【模板】AC自动机(加强版)

Code

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define LL long long
using namespace std;
const int N=15005;
int n,rot,ans,num[N],pos[N],trie[N][26],nxt[N];
char pat[155][N],txt[1000005];
void insert(char s[],int b)
{
	int u=0,len=strlen(s+1);
	for(int i=1;i<=len;i++)
	{
		int v=s[i]-'a';
		if(!trie[u][v]) trie[u][v]=++rot;
		u=trie[u][v];
	}
	pos[u]=b;
	return;
}
void bfs()
{
	queue<int> q;
	for(int i=0;i<26;i++) if(trie[0][i]) q.push(trie[0][i]);
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(int i=0;i<26;i++)
		{
			if(trie[u][i])
			{
				nxt[trie[u][i]]=trie[nxt[u]][i];
				q.push(trie[u][i]);
			}
			else trie[u][i]=trie[nxt[u]][i];
		}
	}
	return;
}
void find(char s[])
{
	int u=0,len=strlen(s+1);
	for(int i=1;i<=len;i++)
	{
		int v=s[i]-'a';
		for(int j=trie[u][v];j;j=nxt[j])
		{
			if(pos[j])
			{
				num[pos[j]]++;
				ans=max(ans,num[pos[j]]);
			}
		}
		u=trie[u][v];
	}
	return;
}
int main()
{
	while(1)
	{
		scanf("%d",&n);
		if(n==0) break;
		rot=0;
		memset(trie,0,sizeof(trie));
		memset(pos,0,sizeof(pos));
	    for(int i=1;i<=n;i++)
	    {
		    cin>>(pat[i]+1);
		    insert(pat[i],i);
	    }
	    memset(nxt,0,sizeof(nxt));
	    bfs();
	    cin>>(txt+1);
	    ans=0;
	    memset(num,0,sizeof(num));
	    find(txt);
	    printf("%d\n",ans);
	    for(int i=1;i<=n;i++) if(num[i]==ans) cout<<(pat[i]+1)<<endl;
	}
	return 0;
}


3.Libre 10057 Keywords Search

Code

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define LL long long
using namespace std;
const int N=5e5+5;
int T,n,rot,nxt[N],num[N],trie[N][26];
char pat[55],txt[1000005];
void insert(char s[])
{
	int u=0,len=strlen(s+1);
	for(int i=1;i<=len;i++)
	{
		int v=s[i]-'a';
		if(!trie[u][v]) trie[u][v]=++rot;
		u=trie[u][v];
	}
	num[u]++;
	return;
}
void bfs()
{
	queue<int> q;
	for(int i=0;i<26;i++) if(trie[0][i]) q.push(trie[0][i]);
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(int i=0;i<26;i++)
		{
			if(trie[u][i])
			{
				nxt[trie[u][i]]=trie[nxt[u]][i];
				q.push(trie[u][i]);
			}
			else trie[u][i]=trie[nxt[u]][i];
		}
	}
	return;
}
int find(char s[])
{
	int u=0,res=0,len=strlen(s+1);
	for(int i=1;i<=len;i++)
	{
		int v=s[i]-'a';
		for(int j=trie[u][v];j&&num[j]!=-1;j=nxt[j])
		{
			res+=num[j];
			num[j]=-1;
		}
		u=trie[u][v];
	}
	return res;
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		rot=0;
		memset(trie,0,sizeof(trie));
		memset(num,0,sizeof(num));
		for(int i=1;i<=n;i++)
		{
			cin>>(pat+1);
			insert(pat);
		}
		memset(nxt,0,sizeof(nxt));
		bfs();
		cin>>(txt+1);
		printf("%d\n",find(txt));
	}
	return 0;
}
posted @ 2019-09-07 11:03  Hawking_llfz  阅读(142)  评论(0编辑  收藏  举报