字符串 AC自动机
AC自动机的板子简单版。
代码如下。
#include<bits/stdc++.h> #define sc(x) scanf("%d",&x) using namespace std; const int maxn=1e6+10; int n,cnt; struct trie{ int fail,num; int ch[30]; #define fa(x) ac[x].fail #define nu(x) ac[x].num }ac[maxn]; inline void insert(string s){ int len=s.length(); int now=0; for(int i=0;i<len;i++){ if(!ac[now].ch[s[i]-'a']) ac[now].ch[s[i]-'a']=++cnt; now=ac[now].ch[s[i]-'a']; } nu(now)++; } //bfs inline void getfail(){ queue<int> q; for(int i=0;i<=26;i++) if(ac[0].ch[i]) fa(ac[0].ch[i])=0,q.push(ac[0].ch[i]); while(!q.empty()){ int now=q.front(); q.pop(); for(int i=0;i<26;i++){ if(ac[now].ch[i]){ fa(ac[now].ch[i])=ac[fa(now)].ch[i]; q.push(ac[now].ch[i]); } else ac[now].ch[i]=ac[fa(now)].ch[i]; } } } inline int ask(string s){ int len=s.length(); int now=0,ans=0; for(int i=0;i<len;i++){ now=ac[now].ch[s[i]-'a']; for(int j=now;j&&nu(j)!=-1;j=fa(j)){ ans+=nu(j); nu(j)=-1; } } return ans; } int main() { sc(n); string s; for(int i=1;i<=n;i++){ cin>>s; insert(s); } fa(0)=0; getfail(); cin>>s; printf("%d\n",ask(s)); return 0; }
AC自动机节点存什么信息比较重要。
各个题目都不太一样。
需要个别的分析。
具体题目见题解。
加强版:
#include<bits/stdc++.h> using namespace std; int n,cnt; const int maxn=1e6+10; string c[200]; int en[maxn]; int ans[300]; struct acc{ int fail,ch[26]; #define fail(x) ac[x].fail }ac[maxn]; inline void insert(string s,int x){ int len=s.length(); int p=0; for(int i=0;i<len;i++){ if(!ac[p].ch[s[i]-'a']) ac[p].ch[s[i]-'a']=++cnt; p=ac[p].ch[s[i]-'a']; } en[p]=x; } inline void getfail(){ queue<int> q; for(int i=0;i<26;i++) if(ac[0].ch[i]) q.push(ac[0].ch[i]),fail(ac[0].ch[i])=0; while(q.size()){ int p=q.front(); q.pop(); for(int i=0;i<26;i++){ if(ac[p].ch[i]) fail(ac[p].ch[i])=ac[fail(p)].ch[i],q.push(ac[p].ch[i]); else ac[p].ch[i]=ac[fail(p)].ch[i]; } } } inline void work(string s){ int len=s.length(); int now=0; for(int i=0;i<len;i++){ now=ac[now].ch[s[i]-'a']; for(int j=now;j;j=fail(j)) ans[en[j]]++; } } int main() { while(scanf("%d",&n)&&n!=0){ memset(en,0,sizeof(en)); memset(ans,0,sizeof(ans)); memset(ac,0,sizeof(ac)); for(int i=1;i<=n;i++){ cin>>c[i]; insert(c[i],i); } getfail(); string s; cin>>s; work(s); int now=0; for(int i=1;i<=n;i++) if(ans[i]>now) now=ans[i]; printf("%d\n",now); for(int i=1;i<=n;i++) if(ans[i]==now) cout<<c[i]<<endl; } // system("pause"); return 0; }