题解 P3796 【【模板】AC自动机(加强版)】
可能会是第一个题解...也只是来水一发
鉴于我水平太差,也没有完全理解这算法.甚至自己的程序(搬运了其他题)
各类资料应该也很多,丑陋的代码仅作为参考
#include<iostream>
#include<string.h>
using namespace std;
#define rep(i,x,y) for(int i=(x);i<=(y);i++)
const int MC=26;
struct T{//trie的一个结点吧..
T *Pre[MC],*F;
int Num;
T(){memset(Pre,0,sizeof Pre),F=0,Num=0;}
}*R;
void I(char s[],int k){//插入一个模式串
T *p=R;
for(int i=0;s[i];i++){
if(p->Pre[s[i]-'a']==0) p->Pre[s[i]-'a']=new T();
p=p->Pre[s[i]-'a'];
}
p->Num=k;//仅仅记录该节点表示的模式串,如有重复模式串,应该会有问题
}
T *q[600005];
void Build(){//构造DFA
int t=0;
R->F=R;
rep(j,0,MC-1) if(R->Pre[j]==0) R->Pre[j]=R;
else{
q[++t]=R->Pre[j];
q[t]->F=R;
}
rep(cur,1,t){
T *i=q[cur];
rep(j,0,MC-1) if(i->Pre[j]!=0){
T *k=i->F;
while(k->Pre[j]==0) k=k->F;
k=k->Pre[j];
q[++t]=i->Pre[j];
q[t]->F=k;
}
}
}
int n,ans,f[152];
char s[1000005],t[152][72];
int main(){
cin>>n;
while(n){
R=new T();
rep(i,1,n) scanf("%s",&t[i]),I(t[i],i);//插入模式串
Build();
scanf("%s",&s);
T *cur=R;
ans=0;
for(int i=0;s[i];i++){
int k=s[i]-'a';
while(cur->Pre[k]==0) cur=cur->F;
cur=cur->Pre[k];
for(T *tmp=cur;1;tmp=tmp->F){
++f[tmp->Num];// f[i]表示第i个模式串出现次数
if(tmp==tmp->F) break;
}
}
rep(i,1,n) ans=max(ans,f[i]);
printf("%d\n",ans);
rep(i,1,n) if(f[i]==ans) printf("%s\n",t[i]);
cin>>n;
memset(f,0,sizeof f);
}
return 0;
}