洛谷P3796 【模板】AC自动机(加强版)
题目描述
有N个由小写字母组成的模式串以及一个文本串T。每个模式串可能会在文本串中出现多次。你需要找出哪些模式串在文本串T中出现的次数最多。
输入输出格式
输入格式:
输入含多组数据。
每组数据的第一行为一个正整数N,表示共有N个模式串,1≤N≤150。
接下去N行,每行一个长度小于等于70的模式串。下一行是一个长度小于等于10^6的文本串TT。
输入结束标志为N=0。
输出格式:
对于每组数据,第一行输出模式串最多出现的次数,接下去若干行每行输出一个出现次数最多的模式串,按输入顺序排列。
输入输出样例
输出样例#1:
View Code
4 aba 2 alpha haha
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 long long read() 7 { 8 long long x=0,f=1; 9 char ch=getchar(); 10 while(ch>'9'||ch<'0') 11 { 12 if(ch=='-') 13 f=-1; 14 ch=getchar(); 15 } 16 while(ch>='0'&&ch<='9') 17 { 18 x=x*10+ch-'0'; 19 ch=getchar(); 20 } 21 return x*f; 22 } 23 const int maxn=3e5+10; 24 string mob[maxn]; 25 int num[maxn],ch[maxn][26],fail[maxn],ans[maxn]; 26 int temp,n,siz; 27 void insert(string s,int v) 28 { 29 int now=0; 30 for(int i=0; i<s.size(); i++) 31 { 32 int o=s[i]-'a'; 33 if(!ch[now][o]) 34 ch[now][o]=++siz; 35 now=ch[now][o]; 36 } 37 num[now]=v; 38 } 39 void getfail() 40 { 41 int now=0; 42 queue<int>q; 43 for(int i=0; i<26; i++) 44 if(ch[0][i]) 45 q.push(ch[0][i]),fail[ch[0][i]]=0; 46 while(!q.empty()) 47 { 48 int u=q.front(); 49 q.pop(); 50 for(int i=0; i<26; i++) 51 { 52 int v=ch[u][i]; 53 if(v) 54 fail[v]=ch[fail[u]][i],q.push(v); 55 else 56 ch[u][i]=ch[fail[u]][i]; 57 } 58 } 59 } 60 void query(string s) 61 { 62 int now=0; 63 for(int i=0; i<s.size(); i++) 64 { 65 now=ch[now][s[i]-'a']; 66 for(int j=now; j; j=fail[j]) 67 ans[num[j]]++; 68 } 69 } 70 int main() 71 { 72 while(scanf("%d",&n)&&n) 73 { 74 memset(num,0,sizeof(num)); 75 memset(ans,0,sizeof(ans)); 76 memset(ch,0,sizeof(ch)); 77 memset(fail,0,sizeof(fail)); 78 siz=0; 79 for(int i=1; i<=n; i++) 80 { 81 cin>>mob[i]; 82 insert(mob[i],i); 83 } 84 getfail(); 85 string k; 86 cin>>k; 87 query(k); 88 temp=0; 89 for(int i=1; i<=n; i++) 90 if(ans[i]>temp) 91 temp=ans[i]; 92 printf("%d\n",temp); 93 for(int i=1; i<=n; i++) 94 if(ans[i]==temp) 95 cout<<mob[i]<<"\n"; 96 } 97 return 0; 98 }