AC自动机练习记录

蒟蒻的AC自动机学习笔记

AC自动机

JSOI2007 文本生成器 题解

SDOI2014 数数 题解

Magical String 代码
(s) 缩成最小循环节,特判只有一种字符情况,为 (b_i) 建立AC自动机,静态标记 ( t Dfs+bitset+vector) 得出每个 (b_i)(s) 中出现的位置,将它们模 (s) 的长度作为边建图,用 ( t Bfs) 求无向无权图最小环。

P.S. 模板

//ACAM
int ch[M][26],cnt=1,at[N];
vector<int> f[M];
bitset<1000> vis[M];
void insert(int i,int an,string a){
	int p=0;
	for(int i=0;i<an;i++){
		int c=a[i]-'a';
		if(!ch[p][c]) ch[p][c]=cnt++;
		p=ch[p][c];
	}
	at[i]=p;
}
int fa[M];
void Getac(){
	queue<int> q;
	for(int i=0;i<26;i++)
		if(ch[0][i]) q.push(ch[0][i]);
	while(sz(q)){
		int p=q.front(); q.pop();
		for(int c=0;c<26;c++)
			if(ch[p][c]){
				fa[ch[p][c]]=ch[fa[p]][c];
				q.push(ch[p][c]);
			} else ch[p][c]=ch[fa[p]][c];
	}
}
vector<int> ac[M];
void Dfs(int p){
	for(int v:ac[p]){
		Dfs(v);
		for(int x:f[v])if(!vis[p][x])
			f[p].pb(x),vis[p][x]=true;
	}
}
void Runac(){
	int p=0;
	for(int i=0;i<len;i++){
		p=ch[p][ss[i]-'a'];
		f[p].pb(i);
	}
	// cout<<"?
";
	for(int i=1;i<cnt;i++){
		ac[fa[i]].pb(i);
		assert(fa[i]!=i);
	}
	Dfs(0);
	for(int i=0;i<n;i++)
		for(int x:f[at[i]]) add(x-sz(b[i]),x);
}
原文地址:https://www.cnblogs.com/Wendigo/p/13332833.html