AC自动机
手写了下AC自动机,真正理解了kmp之后手写AC自动机还是很简单的。。。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<queue> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1000100; const int INF=1e9+10; struct Trie { int ch[maxn][26]; int End[maxn]; int f[maxn]; int last[maxn]; int rt,L; int newnode() { ++L; memset(ch[L],-1,sizeof(ch[L])); End[L]=0; return L; } void init() { L=-1; rt=newnode(); } void insert(char *s) { int len=strlen(s); int u=rt; REP(i,0,len-1){ int c=s[i]-'a'; if(ch[u][c]==-1) ch[u][c]=newnode(); u=ch[u][c]; } End[u]++; } int get(int u) { if(!u) return 0; int res=End[u]+get(last[u]); End[u]=0; return res; } int find(char *s) { int res=0; int len=strlen(s); int u=rt; REP(i,0,len-1){ int c=s[i]-'a'; u=ch[u][c]; if(End[u]) res+=get(u); else if(last[u]) res+=get(last[u]); } return res; } void build() { queue<int> q; REP(c,0,25){ if(~ch[rt][c]) q.push(ch[rt][c]),f[ch[rt][c]]=rt; else ch[rt][c]=rt; } while(!q.empty()){ int u=q.front();q.pop(); last[u]=rt; REP(c,0,25){ if(~ch[u][c]) f[ch[u][c]]=ch[f[u]][c],q.push(ch[u][c]); else ch[u][c]=ch[f[u]][c]; if(End[f[u]]) last[u]=f[u]; else last[u]=last[f[u]]; } } } };Trie ac; int n; char s[maxn],t[maxn]; int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif // ONLINE_JUDGE int T;cin>>T; while(T--){ scanf("%d",&n); ac.init(); REP(i,1,n){ scanf("%s",t); ac.insert(t); } ac.build(); scanf("%s",s); printf("%d\n",ac.find(s)); } return 0; }
我觉得还是把上面找last的语句写到循环的外面比较好,虽然没什么区别,但写到外面才是准确的,谁叫我有代码强迫症。。。还是懒得改了,下次就写到外面吧。。。
没有AC不了的题,只有不努力的ACMER!