题目大意
给定n个由小写字母组成的字符串和一个文本串T,你的任务是找出那些字符串在文本中出现的次数最多
题解
一个文本串,多个模式串,这刚好是AC自动机处理的问题
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <string> #include <queue> using namespace std; const int maxnode=11111; const int sigma_size=26; const int maxs=160; map<string,int> ms; struct AhoCorasickAutomata { int ch[maxnode][sigma_size],last[maxnode]; int fail[maxnode],end[maxnode],cnt[160]; int sz; void init() { memset(ch[0],0,sizeof(ch[0])); memset(cnt,0,sizeof(cnt)); sz=1,ms.clear(); } int idx(char c){return c-'a';} void insert(char *s,int v) { int u=0,n=strlen(s); for(int i=0;i<n;i++) { int c=idx(s[i]); if(!ch[u][c]) { memset(ch[sz],0,sizeof(ch[sz])); end[sz]=0; ch[u][c]=sz++; } u=ch[u][c]; } end[u]=v,ms[string(s)]=v; } void getfail() { queue<int>q; fail[0]=0; for(int c=0;c<sigma_size;c++) { int u=ch[0][c]; if(u){ fail[u]=0;q.push(u);last[u]=0;} } while(!q.empty()) { int r=q.front();q.pop(); for(int c=0;c<sigma_size;c++) { int u=ch[r][c]; if(!u){ch[r][c]=ch[fail[r]][c];continue;} q.push(u); fail[u]=ch[fail[r]][c]; last[u] = end[fail[u]]?fail[u]:last[fail[u]]; } } } void count(int j) { if(j) { cnt[end[j]]++; count(last[j]); } } void find(char *T) { int n=strlen(T); int j=0; for(int i=0;i<n;i++) { int c=idx(T[i]); j=ch[j][c]; if(end[j]) count(j); else if(last[j]) count(last[j]); } } }; AhoCorasickAutomata ac; char text[1000005],P[160][80]; int main() { int n; while(scanf("%d",&n)!=EOF&&n) { ac.init(); for(int i=1;i<=n;i++) { scanf("%s",P[i]); ac.insert(P[i],i); } ac.getfail(); scanf("%s",text); ac.find(text); int best=-1; for(int i=1;i<=n;i++) if(ac.cnt[i]>best) best=ac.cnt[i]; printf("%d ",best); for(int i=1;i<=n;i++) if(ac.cnt[ms[string(P[i])]]==best) printf("%s ",P[i]); } return 0; }