ac自动机 模板

/*
洛谷 p3796
题意:n个模式串 一个文本串 问这个n个模式串最多的一个或者多个
出现在文本串里的个数 顺便输出这个最多的文本串 
*/ 
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+1000;
int ans[N*10];
char s[N*10];
struct tire
{
	int sz=0,ch[N][26],fail[N],num[N];
	void Init(){
		sz=0;
		memset(ch,0,sizeof(ch));
		memset(fail,0,sizeof(fail));
		memset(num,0,sizeof(num));
		memset(ans,0,sizeof(ans));
	}
	void Insert(char *s,int v){
		int root=0;
		int len=strlen(s);
		for(int i=0;i<len;i++){
			int t=s[i]-'a';
			if(!ch[root][t]) ch[root][t]=++sz;
			root=ch[root][t]; 
		}
		num[root]=v;//标记一下
		//num[root]++ 出现多少次用的 
	}
	void build(){
		queue<int>Q;
		for(int i=0;i<26;i++){
			if(ch[0][i]){
				Q.push(ch[0][i]);
				fail[ch[0][i]]=0;
			}
		}
		while(!Q.empty()){
			int u=Q.front();
			Q.pop();
			for(int i=0;i<26;i++){
				int t=ch[u][i];
				if(t){
					fail[t]=ch[fail[u]][i];
					Q.push(t);
				}
				else ch[u][i]=ch[fail[u]][i];
			}
		}
	}
	
	void query(char *s){
		int root=0;
		int len=strlen(s);
		for(int i=0;i<len;i++){
			root=ch[root][s[i]-'a'];
			for(int j=root;j;j=fail[j]){
				ans[num[j]]++;
			}
		}
	}
	void debug(){
        for(int i = 0;i <=sz;i++){
            printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],num[i]);
            for(int j = 0;j < 26;j++)
                printf("%2d",ch[i][j]);
            printf("]\n");
        }
    }
}ac;
char tt[200][100];
int main()
{
	int n;
	while(scanf("%d",&n)==1&&n){
		ac.Init();
		for(int i=1;i<=n;i++){
			scanf("%s",tt[i]);
			ac.Insert(tt[i],i);
		}
		ac.build();
		scanf("%s",s);
		ac.query(s);
		int t=0;
		for(int i=1;i<=n;i++){
			if(ans[i]>t) t=ans[i];
		}
		printf("%d\n",t);
		for(int i=1;i<=n;i++){
			if(ans[i]==t){
				printf("%s\n",tt[i]);
			}
		}
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/CC_1012/article/details/94720542