LA 4670 Dominating Patterns

        题意:给出n个单词和一个长字符串,找出在长字符串里出现次数最多的单词,输出出现次数和单词。如果多个单词出现次数同为最多,按输入顺序输出单词。

        思路:AC自动机。题意非常明显,应该算是AC自动机的模板题。我的理解是,AC自动机就是字典树和KMP算法的结合,如果匹配失败了,节点就在树上跳转,跳转到可能匹配的深度最大的节点(当然与原节点相比深度会减小)。这题用AC自动机匹配并统计,然后扫一遍输入的单词,符合条件的输出即可。


#include <iostream>           
#include <stdio.h>           
#include <cmath>           
#include <algorithm>           
#include <iomanip>           
#include <cstdlib>           
#include <string>           
#include <memory.h>           
#include <vector>           
#include <queue>           
#include <stack>           
#include <map>         
#include <set>         
#include <ctype.h>         
#define INF 1<<30       
#define ll long long       
#define max3(a,b,c) max(a,max(b,c))       
#define MAXN 4100000
  
using namespace std;  


char text[1000010];
int ans;
char word[160][80];
int cnt[160];

struct Trie{
	int ch[10510][26];
	char c[10510];
	int val[10510];
	int sz;
	int next[10510];
	int pre[10510];
	
	void init(){
		sz=1; 
		memset(ch,0,sizeof(ch));
		memset(val,0,sizeof(val));
		memset(cnt,0,sizeof(cnt));
	}
	
	void insert(char* str,int w){
		int u=0;
		int len=strlen(str);
		for(int i=0;i<len;i++){
			if( !ch[u][str[i]-'a'] ){
				memset(ch[sz],0,sizeof(ch[sz]));
				c[sz]=str[i];
				ch[u][str[i]-'a']=sz;
				pre[sz]=u;
				sz++;
			}
			u=ch[u][str[i]-'a'];
		}
		val[u]=w;
	}
	
	void build_ac(){
		queue<int> que; que.push(0);
		
		while(!que.empty()){
			int u=que.front(); que.pop();
			if(!u){
				for(int i=0;i<26;i++){
					int v=ch[u][i];
					if( !v )continue;
					next[v]=0;
					que.push(v);
				}
			}else{
				for(int i=0;i<26;i++){
					int v=ch[u][i];
					if(!v)continue;
					int k=next[u];
					while(k&&ch[k][i]==0)k=next[k];
					if(ch[k][i])k=ch[k][i];
					next[v]=k;
					que.push(v);
				}
			}
		}
	}
	
	void query(char* text){
		int u=0;
		int len=strlen(text);
		for(int i=0;i<len;i++){
			int v=ch[u][text[i]-'a'];
			if(v){
				u=v;
				//
				while(val[u]){
					//cout<<"match at "<<i<<endl;
					cnt[val[u]]++;
					if(cnt[val[u]]>ans)ans=cnt[val[u]];
					u=next[u];	
				}	
				while(u&&!ch[u][text[i+1]-'a'])u=next[u];
			}else{
				while(u&&!ch[u][text[i+1]-'a'])u=next[u];
			}
		}
	}
	
};

Trie T;

int main(){
	int n;
	while(cin>>n){
		if(!n)break;
		T.init();
		ans=0;
		
		for(int i=1;i<=n;i++){
			scanf("%s",word[i]);
			T.insert(word[i],i);
		}
		scanf("%s",text);
		T.build_ac();
		T.query(text);
		
		cout<<ans<<endl;
		for(int i=1;i<=n;i++){
			if(cnt[i]==ans){
				printf("%s\n",word[i]);
			}
		}
	}
}


你可能感兴趣的:(AC自动机)