洛谷P3796 【模板】AC 自动机(加强版)
题目描述
有N个由小写字母组成的模式串以及一个文本串T。每个模式串可能会在文本串中出现多次。你需要找出哪些模式串在文本串T中出现的次数最多。
输入格式
输入含多组数据。
每组数据的第一行为一个正整数N,表示共有N个模式串,1≤N≤150。
接下去NN行,每行一个长度小于等于70的模式串。下一行是一个长度小于等于10^6 的文本串T。
输入结束标志为N = 0
输出格式
样例
非常明显,这是一道AC自动机的题经典废话
懒得解释接下来的了,待会发个算法学习得了
#include<bits/stdc++.h> using namespace std; struct answer{ int num,pos; bool operator<(const answer &a){ if(num!=a.num) return num>a.num; else return pos<a.pos; } }ans[1000010]; int n,cnt,ch[1000010][30],f[1000010],val[1000010]; string s[1000],s1; void build(int num){ int len = s[num].length(),now = 0; for(int i = 0;i<len;i++){ if(ch[now][s[num][i]-'a']==0) ch[now][s[num][i]-'a'] = ++cnt; now = ch[now][s[num][i]-'a']; } val[now] = num; } void getfail(){ queue<int>q; for(int i = 0;i<26;++i){ if(ch[0][i]!=0){ f[ch[0][i]] = 0; q.push(ch[0][i]); } } while(!q.empty()){ int u = q.front(); q.pop(); for(int i = 0;i<26;++i){ if(ch[u][i]!=0){ f[ch[u][i]] = ch[f[u]][i]; q.push(ch[u][i]); }else ch[u][i] = ch[f[u]][i]; } } } void acquery(){ int l = s1.length(),now = 0; for(int i = 0;i<l;i++){ now = ch[now][s1[i]-'a']; for(int t = now;t;t = f[t]) ans[val[t]].num++; } } int main(){ scanf("%d",&n); while(n){ memset(f,0,sizeof(f)); memset(val,0,sizeof(val)); memset(ch,0,sizeof(ch)); for(int i = 1;i<=n;i++){ cin>>s[i]; ans[i].num = 0; ans[i].pos = i; build(i); } cin>>s1; f[0] = 0; getfail(); acquery(); sort(ans+1,ans+n+1); printf("%d\n",ans[1].num); cout<<s[ans[1].pos]<<endl; for(int i = 2;i<=n;i++){ if(ans[i].num==ans[1].num) cout<<s[ans[i].pos]<<endl; } scanf("%d",&n); } return 0; }
梦与现实间挣扎着,所求为何
你可以借走我的文章,但你借不走我的智慧 虽然我是傻逼本文来自博客园,作者:cztq,转载请注明原文链接:https://www.cnblogs.com/cztq/p/17045941.html