题目大意:找出出现次数最多的模式串。
题目分析:AC自动机裸题。
代码如下:
# include<iostream> # include<cstdio> # include<map> # include<queue> # include<cstring> # include<algorithm> using namespace std; const int N=20000; int ch[N][26]; string p[155]; char s[N*50+5]; int val[N]; int t[155]; int f[N+5]; int last[N+5]; map<string,int>mp; map<int,string>mpp; struct AC { int cnt; void init() { cnt=0; memset(val,0,sizeof(val)); memset(ch,0,sizeof(ch)); memset(t,0,sizeof(t)); } void insert(string str,int v) { int n=str.size(); int root=0; for(int i=0;i<n;++i){ int c=str[i]-‘a‘; if(!ch[root][c]) ch[root][c]=++cnt; root=ch[root][c]; } val[cnt]=v; } void getFail() { queue<int>q; f[0]=0; for(int i=0;i<26;++i){ int u=ch[0][i]; if(!u) continue; f[u]=0; q.push(u); last[u]=0; } while(!q.empty()){ int r=q.front(); q.pop(); for(int i=0;i<26;++i){ int u=ch[r][i]; if(!u) continue; q.push(u); int v=f[r]; while(v&&!ch[v][i]) v=f[v]; f[u]=ch[v][i]; last[u]=val[f[u]]?f[u]:last[f[u]]; } } } void ac(char *s) { int n=strlen(s); int j=0; for(int i=0;i<n;++i){ int c=s[i]-‘a‘; while(j&&!ch[j][c]) j=f[j]; j=ch[j][c]; if(val[j]) getResult(j); else if(last[j]) getResult(last[j]); } } void getResult(int u) { if(u==0) return ; if(u) ++t[val[u]]; getResult(last[u]); } }ac; int main() { int n; while(~scanf("%d",&n)&&n) { ac.init(); int cnt=0; mp.clear(); mpp.clear(); for(int i=0;i<n;++i){ cin>>p[i]; if(mp[p[i]]==0) mp[p[i]]=++cnt; ac.insert(p[i],cnt); mpp[cnt]=p[i]; } scanf("%s",s); ac.getFail(); ac.ac(s); int maxn=0; for(int i=1;i<=cnt;++i) maxn=max(maxn,t[i]); cout<<maxn<<endl; for(int i=1;i<=cnt;++i) if(t[i]==maxn) cout<<mpp[i]<<endl; } return 0; }
时间: 2024-11-06 03:49:40