AC自动机学习笔记

学了AC自动机就能自动AC
才怪
可以先看yyb老爷的博文,精妙无双
不定期更?
Upd:2019.6.6

001

前置知识:字典树(Trie树),KMP
关于AC自动机,日报上愤怒地指责了当前许多dalao感性地将其表述为Trie+KMP的行为
我:虽然我是菜鸡,但。。。确实是Trie上KMP啊
和KMP一样,AC自动机的失配(fail)指针也是继续匹配用的,而AC自动机主要就是构建fail指针

Code

void getfail()
{
	queue<int>Q;
	for(int i=1;i<=26;i++)
	{
		if(Trie[0].vis[i])
		{
			Trie[Trie[0].vis[i]].fail=0;
			Q.push(Trie[0].vis[i]);
		}
	}
	while(!Q.empty())
	{
		int T=Q.front();
		Q.pop();
		for(int i=1;i<=26;i++)
		{
			if(Trie[T].vis[i])
			{
				Trie[Trie[T].vis[i]].fail=Trie[Trie[T].fail].vis[i];
				Q.push(Trie[T].vis[i]);
			}
			else
			{
				Trie[T].vis[i]=Trie[Trie[T].fail].vis[i];
			}
		}
	}
}

再贴一个Trie?

开个玩笑

Code

struct node
{
	int vis[27],fail,end;
}Trie[1000010];
void build()
{
	int len=strlen(C+1); 
	int now=0;
	for(int i=1;i<=len;i++)
	{
		if(!Trie[now].vis[C[i]-'a'+1])
		{
			Trie[now].vis[C[i]-'a'+1]=++cnt;
		}
		now=Trie[now].vis[C[i]-'a'+1];
	}
	Trie[now].end++;
}

002

板题(减'a'后没加1调了我好久QwQ):
P3808 【模板】AC自动机(简单版)


Code

#include<bits/stdc++.h>
using namespace std;
int n,cnt;
char C[1000010];
struct node
{
	int vis[27],fail,end;
}Trie[1000010];
void build()
{
	int len=strlen(C+1); 
	int now=0;
	for(int i=1;i<=len;i++)
	{
		if(!Trie[now].vis[C[i]-'a'+1])
		{
			Trie[now].vis[C[i]-'a'+1]=++cnt;
		}
		now=Trie[now].vis[C[i]-'a'+1];
	}
	Trie[now].end++;
}
void getfail()
{
	queue<int>Q;
	for(int i=1;i<=26;i++)
	{
		if(Trie[0].vis[i])
		{
			Trie[Trie[0].vis[i]].fail=0;
			Q.push(Trie[0].vis[i]);
		}
	}
	while(!Q.empty())
	{
		int T=Q.front();
		Q.pop();
		for(int i=1;i<=26;i++)
		{
			if(Trie[T].vis[i])
			{
				Trie[Trie[T].vis[i]].fail=Trie[Trie[T].fail].vis[i];
				Q.push(Trie[T].vis[i]);
			}
			else
			{
				Trie[T].vis[i]=Trie[Trie[T].fail].vis[i];
			}
		}
	}
}
int ACJ()
{
	int len=strlen(C+1);
	int now=0,ans=0;
	for(int i=1;i<=len;i++)
	{
		now=Trie[now].vis[C[i]-'a'+1];
		for(int j=now;j&&Trie[j].end!=-1;j=Trie[j].fail)
		{
			ans+=Trie[j].end;
			Trie[j].end=-1; 
		}
	}
	return ans;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",C+1);
		build();
	}
	Trie[0].fail=0;
	getfail();
	scanf("%s",C+1);
	cout<<ACJ();
} 
posted @ 2019-05-26 11:44  G_A_TS  阅读(428)  评论(0编辑  收藏  举报