UVa 1449

题目大意:给出多个字符串模板,并给出一个文本串,求在文本串中出现最多的模板,输出最多的次数并输出该模板(若有多个满足,则按输入顺序输出)。

思路:赤裸裸的 AC自动机,上模板。

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
#define INF 0x7fffffff

char s[160][80],T[1000010];
int nz,cnt,ch[15000][30],num[160],val[315000];
int f[315000],last[315000];

void insert(char a[],int k){
	int i,j,len = strlen(a),u = 0;
	for(i=0;i<len;i++){
		int v = a[i] - 'a' ;
		if(!ch[u][v]){
			memset(ch[nz],0,sizeof(ch[nz]));
			val[nz]=0;
			ch[u][v] = nz++;
		}
		u = ch[u][v];
	}
	val[u] = k;
}

void getFail(){
	int i;
	queue<int> Q;
	while(!Q.empty())
		Q.pop();
	f[0] = 0;
	for(i=0;i<26;i++)
	    if(ch[0][i]){
	    	f[ch[0][i]] = 0;
			Q.push(ch[0][i]);
			last[ch[0][i]] = 0;	
	    }
	while(!Q.empty()){
		int r = Q.front();
		Q.pop();
		for(i=0;i<26;i++){
			int v = ch[r][i];
			if(v){
				Q.push(v);
				int p = f[r];
				while(p && !ch[p][i])
				    p = f[p];
				f[v] = ch[p][i];
				last[v] = val[f[v]] ? f[v] : last[f[v]];
			}
		}
	}
}

void print(int i){
	if(i){
//		printf("%d ",val[i]); 
		num[val[i]]++;
		print(last[i]);
	}
}

void find(){
	int i,j;
	int len = strlen(T);
	int u = 0;
	for(i=0;i<len;i++){
		int v = T[i] - 'a';
		while(u && !ch[u][v]) u = f[u];
		u = ch[u][v];
		if(val[u]) print(u);
		else if(last[u]) print(last[u]);
	} 
}

int main(){
	int n,i,j;
	while(scanf("%d",&n) && n){
		nz = 1;
		memset(val,0,sizeof(val));
		memset(ch[0],0,sizeof(ch));
		memset(num,0,sizeof(num));
		for(i=1;i<=n;i++){
			scanf("%s",s[i]);
			insert(s[i],i);
		}
		scanf("%s",T);
		getFail();
		find();
		int MAX = 0;
		for(i=1;i<=n;i++)
			MAX = max(MAX,num[i]);
		printf("%d
",MAX);
		for(i=1;i<=n;i++)
		    if(num[i] == MAX)
		        printf("%s
",s[i]);
	}

	return 0;
}
原文地址:https://www.cnblogs.com/jxgapyw/p/4780584.html