构建trie树
构建fail树
AC匹配
#include<bits/stdc++.h> #define re return #define inc(i,l,r) for(int i=l;i<=r;++i) using namespace std; template<typename T>inline void rd(T&x) { char c;bool f=0; while((c=getchar())<'0'||c>'9')if(c=='-')f=1; x=c^48; while((c=getchar())>='0'&&c<='9')x=x*10+(c^48); if(f)x=-x; } int n,tot,ans[155]; char ss[155][75],s[1000005]; struct node{ int end,fail,son[26]; }AC[100005]; inline void clean(int x) { for(int i=0;i<=25;++i) AC[x].son[i]=0; AC[x].fail=0; AC[x].end=0; } inline void build(int x) { int len=strlen(ss[x]); int now=0; inc(i,0,len-1)//构建trie树 { if(!AC[now].son[ss[x][i]-'a']) { AC[now].son[ss[x][i]-'a']=++tot; clean(tot);//下一层回档 } now=AC[now].son[ss[x][i]-'a']; } AC[now].end=x;//标记访问节点标号 } inline void Get_fail() { queue<int>Q; inc(i,0,25)//预处理第一层 { if(AC[0].son[i]) { AC[AC[0].son[i]].fail=0; Q.push(AC[0].son[i]); } } while(!Q.empty()) { int u=Q.front(); Q.pop(); inc(i,0,25) { if(AC[u].son[i])//存在 { AC[AC[u].son[i]].fail=AC[AC[u].fail].son[i];//子节点的fail指向该父节点的fail Q.push(AC[u].son[i]); } else //不存在 AC[u].son[i]=AC[AC[u].fail].son[i];//子节点直接指向该fail的son[i] } } } inline void Get_ans() { int now=0; int len=strlen(s); inc(i,0,len-1) { now=AC[now].son[s[i]-'a']; for(int t=now;t;t=AC[t].fail) ++ans[AC[t].end]; } } int main() { freopen("in.txt","r",stdin); while(2333) { rd(n); if(!n) break; tot=0; clean(0);//清0 inc(i,1,n) { scanf("%s",ss[i]); ans[i]=0; build(i); } AC[0].fail=0; Get_fail(); scanf("%s",s); Get_ans(); int maxx=0; inc(i,1,n) maxx=max(ans[i],maxx); printf("%d ",maxx); inc(i,1,n) if(ans[i]==maxx) printf("%s ",ss[i]); } re 0; }