题目链接:http://vjudge.net/problem/36265
#include<bits/stdc++.h> #define N 200 using namespace std; const int maxnode=11000; const int sigma_size=26; int res[N]; struct AC_Automata { int ch[maxnode][sigma_size]; int val[maxnode]; /// 每个字符串的结尾结点都有一个非0的val int f[maxnode]; /// fail函数 int last[maxnode]; /// last[i]=j表j节点表示的单词是i节点单词的后缀,且j节点是单词节点 int sz; ///初始化0号根节点的相关信息 void init() { sz=1; memset(ch[0],0,sizeof(ch[0])); memset(res,0,sizeof res); val[0]=0; } ///Insert负责构造ch与val数组 ///插入字符串,v必须非0表示一个单词节点 void Insert(char *s,int v) { int n=strlen(s),u=0; for(int i=0; i<n; i++) { int id=s[i]-'a'; if(ch[u][id]==0) { ch[u][id]=sz; memset(ch[sz],0,sizeof(ch[sz])); val[sz++]=0; } u=ch[u][id]; } val[u]=v; } ///getFail函数负责构造f和last数组 void getFail()///bfs的作用就是从根节点开始向下进行路径的遍历,从而达到线性求next数组的作用 { queue<int> q; last[0]=f[0]=0; for(int i=0; i<sigma_size; i++) { int u=ch[0][i]; if(u) { f[u]=last[u]=0; q.push(u); } } while(!q.empty())/// 按BFS顺序计算fail { int r=q.front(); q.pop(); for(int i=0;i<sigma_size;i++)///找它的儿子 { int u=ch[r][i]; if(u==0)continue;///为0的话肯定不是它的儿子 q.push(u); int v=f[r]; while(v && ch[v][i]==0) v=f[v]; f[u]= ch[v][i]; last[u] = val[f[u]]?f[u]:last[f[u]]; } } } /// 在s中找出 出现了哪几个模板单词 void Find(char *s) { int n=strlen(s),j=0; for(int i=0; i<n; i++) { int id=s[i]-'a'; while(j && ch[j][id]==0) j=f[j];///找与他能匹配的最大位置 j=ch[j][id]; if(val[j]) { print(j); } else if(last[j]) { print(last[j]); } } } ///递归打印与结点i后缀相同的前缀节点编号 ///进入此函数前需保证val[i]>0 void print(int i) { if(val[i]) { res[val[i]]++; print(last[i]); } } }; AC_Automata ac; char word[N][N/2]; char op[1000005]; int main() { //freopen("C:\Users\acer\Desktop\in.txt","r",stdin); int n; while(scanf("%d",&n)!=EOF&&n) { ac.init(); for(int i=1;i<=n;i++) { scanf("%s",&word[i]); ac.Insert(word[i],i); } ac.getFail(); scanf("%s",op); ac.Find(op); int maxn=-1; for(int i=1;i<=n;i++) if(res[i]>maxn) maxn=res[i]; printf("%d ",maxn); int c=0; for(int i=1;i<=n;i++) { if(res[i]==maxn) { if(c) puts(""); c++; printf("%s",word[i]); } } printf(" "); } return 0; }