UVALive-4670 Dominating Patterns(AC自动机)

题目大意:找出出现次数最多的模式串。

题目分析:AC自动机裸题。

代码如下:

# include<iostream>
# include<cstdio>
# include<map>
# include<queue>
# include<cstring>
# include<algorithm>
using namespace std;

const int N=20000;

int ch[N][26];
string p[155];
char s[N*50+5];
int val[N];
int t[155];
int f[N+5];
int last[N+5];
map<string,int>mp;
map<int,string>mpp;

struct AC
{
	int cnt;
	void init()
	{
		cnt=0;
		memset(val,0,sizeof(val));
		memset(ch,0,sizeof(ch));
		memset(t,0,sizeof(t));
	}
	
	void insert(string str,int v)
	{
		int n=str.size();
		int root=0;
		for(int i=0;i<n;++i){
			int c=str[i]-'a';
			if(!ch[root][c])
				ch[root][c]=++cnt;
			root=ch[root][c];
		}
		val[cnt]=v;
	}
	
	void getFail()
	{
		queue<int>q;
		f[0]=0;
		for(int i=0;i<26;++i){
			int u=ch[0][i];
			if(!u) continue;
			f[u]=0;
			q.push(u);
			last[u]=0;
		}
		while(!q.empty()){
			int r=q.front();
			q.pop();
			for(int i=0;i<26;++i){
				int u=ch[r][i];
				if(!u) continue;
				q.push(u);
				int v=f[r];
				while(v&&!ch[v][i]) v=f[v];
				f[u]=ch[v][i];
				last[u]=val[f[u]]?f[u]:last[f[u]];
			}
		}
	}
	
	void ac(char *s)
	{
		int n=strlen(s);
		int j=0;
		for(int i=0;i<n;++i){
			int c=s[i]-'a';
			while(j&&!ch[j][c]) j=f[j];
			j=ch[j][c];
			if(val[j]) getResult(j);
			else if(last[j]) getResult(last[j]);
		}
	}
	
	void getResult(int u)
	{
		if(u==0) return ;
		if(u) ++t[val[u]];
		getResult(last[u]);
	}
}ac;

int main()
{
	int n;
	while(~scanf("%d",&n)&&n)
	{
		ac.init();
		int cnt=0;
		mp.clear();
		mpp.clear();
		for(int i=0;i<n;++i){
			cin>>p[i];
			if(mp[p[i]]==0) mp[p[i]]=++cnt;
			ac.insert(p[i],cnt);
			mpp[cnt]=p[i];
		}
		scanf("%s",s);
		
		ac.getFail();
		ac.ac(s);
		int maxn=0;
		for(int i=1;i<=cnt;++i)
			maxn=max(maxn,t[i]);
		cout<<maxn<<endl;
		for(int i=1;i<=cnt;++i)
			if(t[i]==maxn) cout<<mpp[i]<<endl;
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/20143605--pcx/p/5752840.html