其他分享
首页 > 其他分享> > AC自动机

AC自动机

作者:互联网

oj传送门
本质上是在trie树上套kmp的next数组(fail数组),用bfs按逐层遍历可以保证不重复和遗漏。

\\题目中要求出模式串重复次数,由于模式串自身较短,可以暴力失配找后缀匹配的模式串
#include<bits/stdc++.h>
using namespace std;
const int maxn=150*70+100;
const int maxm=1e6+100;
struct node{
	int a[26];
	int id;
	int fail;
}ac[maxn];int tot;
string s;
string t[155];
int n,m;
inline void build_fail(){
	queue<int>q;
	ac[0].fail=0;
	for(int i=0;i<26;i++){
		if(ac[0].a[i]){
			ac[ac[0].a[i]].fail=0;
			q.push(ac[0].a[i]);
		}
	}
	while(!q.empty()){
		int u=q.front(),v;q.pop();
		for(int i=0;i<26;i++){
			if(ac[u].a[i]){
				v=ac[u].fail;
				while(v&&!ac[v].a[i])v=ac[v].fail;
				if(ac[v].a[i])v=ac[v].a[i];
				ac[ac[u].a[i]].fail=v;
				q.push(ac[u].a[i]);
			}
		} 
	}
}
int ans[155];
void ac_query(){
	int now=0;
	for(auto r:s){
		while(now&&!ac[now].a[r-'a'])
			now=ac[now].fail;
		if(ac[now].a[r-'a'])now=ac[now].a[r-'a'];
		for(int t=now;t;t=ac[t].fail){
			ans[ac[t].id]++;
		}
	}
}
signed main(){
//	ios::sync_with_stdio(false);
	cin.tie(0);
	while(cin>>n&&n!=0){
		for(int i=1;i<=n;i++)
			cin>>t[i];
		memset(ac,0,sizeof ac);tot=0;
		for(int i=1;i<=n;i++){
			int now=0;
			for(auto r:t[i]){
				if(!ac[now].a[r-'a'])
					ac[now].a[r-'a']=++tot;
				now=ac[now].a[r-'a'];
			}
			ac[now].id=i;
		}
		build_fail();
		memset(ans,0,sizeof ans);
		cin>>s;
		ac_query();
		vector<int>Ans;int mx=-1;
		for(int i=1;i<=n;i++){
			if(ans[i]>mx){
				mx=ans[i];
				Ans.clear();
				Ans.push_back(i);
			}
			else if(ans[i]==mx){
				Ans.push_back(i);
			}
		}
//		printf("%d\n",mx);
		cout<<mx<<endl;
		for(auto r:Ans){
			cout<<t[r]<<endl;
		}
	}
	return 0;
}

标签:AC,int,ac,back,Ans,fail,自动机,mx
来源: https://www.cnblogs.com/xyc1719/p/16523105.html