1. 程式人生 > >模板 AC自動機

模板 AC自動機

oid 一行 i++ else amp content ring lan algorithm

題目描述

有$N$ 個由小寫字母組成的模式串以及一個文本串$T$ 。每個模式串可能會在文本串中出現多次。你需要找出哪些模式串在文本串$T$ 中出現的次數最多。

輸入輸出格式

輸入格式:

輸入含多組數據。

每組數據的第一行為一個正整數$N$ ,表示共有$N$ 個模式串,$1 \leq N \leq 150$ 。

接下去$N$ 行,每行一個長度小於等於$70$ 的模式串。下一行是一個長度小於等於$10^6$ 的文本串$T$ 。

輸入結束標誌為$N=0$ 。

輸出格式:

對於每組數據,第一行輸出模式串最多出現的次數,接下去若幹行每行輸出一個出現次數最多的模式串,按輸入順序排列。

輸入輸出樣例

輸入樣例#1:
2
aba
bab
ababababac
6
beta
alpha
haha
delta
dede
tata
dedeltalphahahahototatalpha
0
輸出樣例#1:
4
aba
2
alpha
haha
傳送門
AC自動機板子
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6
#include<queue> 7 using namespace std; 8 char s[152][72],ss[1000001]; 9 int n,ch[15001][27],size,val[15001],f[15001],ans,cnt[15001],ansnum; 10 queue<int>Q; 11 void insert(int len,int id) 12 {int i; 13 int now=0; 14 for (i=0;i<len;i++) 15 { 16 if (ch[now][s[id][i]-a]==0)
17 ch[now][s[id][i]-a]=++size; 18 now=ch[now][s[id][i]-a]; 19 } 20 val[now]=id; 21 } 22 void AC_build() 23 {int i; 24 for (i=0;i<26;i++) 25 if (ch[0][i]) 26 f[ch[0][i]]=0,Q.push(ch[0][i]); 27 while (Q.empty()==0) 28 { 29 int u=Q.front(); 30 Q.pop(); 31 for (i=0;i<26;i++) 32 { 33 if (ch[u][i]) f[ch[u][i]]=ch[f[u]][i],Q.push(ch[u][i]); 34 else ch[u][i]=ch[f[u]][i]; 35 } 36 } 37 } 38 void query() 39 {int i,j; 40 int now=0; 41 int len=strlen(ss); 42 for (i=0;i<len;i++) 43 { 44 now=ch[now][ss[i]-a]; 45 for (j=now;j&&val[j]!=-1;j=f[j]) 46 cnt[val[j]]++; 47 } 48 } 49 int main() 50 {int i; 51 while (cin>>n&&n) 52 { 53 size=0; 54 memset(ch,0,sizeof(ch)); 55 memset(cnt,0,sizeof(cnt)); 56 memset(val,0,sizeof(val)); 57 for (i=1;i<=n;i++) 58 { 59 scanf("%s",s[i]); 60 insert(strlen(s[i]),i); 61 } 62 AC_build(); 63 scanf("%s",ss); 64 query(); 65 ans=0; 66 for (i=1;i<=n;i++) 67 if (cnt[i]>ans) 68 { 69 ans=cnt[i]; 70 } 71 printf("%d\n",ans); 72 for (i=1;i<=n;i++) 73 if (cnt[i]==ans) 74 { 75 printf("%s\n",s[i]); 76 } 77 } 78 }

模板 AC自動機