模板 AC自動機
阿新 • • 發佈:2018-02-10
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自動機