luogu3808 luogu3796 AC自动机(简单版) AC自动机(加强版)

纪念一下我一晚上写了八遍AC自动机

这是加强版的:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
int n, cnt[155], mp[155], len, maxn;
char a[155][75], b[1000005];
queue<int> d;
struct ACzdj{
	int s[10505][26], val[10505], lst[10505], fai[10505], u, v, siz;
	//lst[i]是节点i沿失配指针走时遇到的第一个单词节点编号
	void clr(){
		siz = maxn = 0;
		memset(s, 0, sizeof(s));
		memset(cnt, 0, sizeof(cnt));
		memset(val, 0, sizeof(val));
		memset(lst, 0, sizeof(lst));
		memset(fai, 0, sizeof(fai));
	}
	void ins(int k){
		u = 0;
		len = strlen(a[k]);
		for(int i=0; i<len; i++){
			v = a[k][i] - 'a';
			if(!s[u][v])	s[u][v] = ++siz;
			u = s[u][v];
		}
		if(!val[u])	val[u] = k;
		mp[k] = val[u];
	}
	void getFail(){
		for(int i=0; i<26; i++)
			if(s[0][i])
				d.push(s[0][i]);
		while(!d.empty()){
			u = d.front();
			d.pop();
			for(int i=0; i<26; i++){
				v = s[u][i];
				if(v){
					fai[v] = s[fai[u]][i];
					lst[v] = val[fai[v]]?fai[v]:lst[fai[v]];
					d.push(v);
				}
				else	s[u][i] = s[fai[u]][i];
			}
		}
	}
	void query(){
		u = 0;
		len = strlen(b);
		for(int i=0; i<len; i++){
			u = s[u][b[i]-'a'];
			if(val[u])	cnt[val[u]]++;
			v = lst[u];
			while(v){
				cnt[val[v]]++;
				v = lst[v];
			}
		}
		for(int i=1; i<=n; i++)
			maxn = max(maxn, cnt[i]);
		printf("%d
", maxn);
		for(int i=1; i<=n; i++)
			if(cnt[mp[i]]==maxn)
				printf("%s
", a[i]);
	}
}ac;
int main(){
	while(scanf("%d", &n)!=EOF){
		if(!n)	break;
		ac.clr();
		for(int i=1; i<=n; i++){
			scanf("%s", a[i]);
			ac.ins(i);
		}
		ac.getFail();
		scanf("%s", b);
		ac.query();
	}
	return 0;
}

这是简单版的:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
char a[1000005];
queue<int> d;
int n;
struct ACzdj{
	int s[1000005][26], siz, u, v, len, val[1000005], mp[1000005], fai[1000005];
	int cnt[1000005], lst[1000005];
	void ins(int k){
		u = 0;
		len = strlen(a);
		for(int i=0; i<len; i++){
			v = a[i] - 'a';
			if(!s[u][v])	s[u][v] = ++siz;
			u = s[u][v];
		}
		if(!val[u])	val[u] = k;
		mp[k] = val[u];
	}
	void getFail(){
		u = 0;
		for(int i=0; i<26; i++)
			if(s[0][i])
				d.push(s[0][i]);
		while(!d.empty()){
			u = d.front();
			d.pop();
			for(int i=0; i<26; i++){
				v = s[u][i];
				if(v){
					fai[v] = s[fai[u]][i];
					lst[v] = val[fai[v]]?fai[v]:lst[fai[v]];
					d.push(v);
				}
				else	s[u][i] = s[fai[u]][i];
			}
		}
	}
	void query(){
		u = 0;
		len = strlen(a);
		for(int i=0; i<len; i++){
			u = s[u][a[i]-'a'];
			if(val[u])	cnt[val[u]]++;
			v = lst[u];
			while(v){
				cnt[val[v]]++;
				v = lst[v];
			}
		}
		int ans=0;
		for(int i=1; i<=n; i++)
			if(cnt[mp[i]])
				ans++;
		cout<<ans<<endl;
	}
}ac;
int main(){
	cin>>n;
	for(int i=1; i<=n; i++){
		scanf("%s", a);
		ac.ins(i);
	}
	ac.getFail();
	scanf("%s", a);
	ac.query();
	return 0;
}
原文地址:https://www.cnblogs.com/poorpool/p/7989555.html