AC自动机
拓扑排序优化,注意拓扑排序前要把所有入度为零的点都加进去
#include<bits/stdc++.h> using namespace std; #define maxn 1000005 #define maxm 28 struct AC { int trieN; int ch[maxn][maxm]; int val[maxn]; int fail[maxn]; int ans[maxn]; int in[maxn];///用于拓扑排序 vector<int> s[maxn]; int tim[maxn]; void init() { trieN=-1; newnod(); } int newnod() { memset(ch[++trieN],0,sizeof ch[0]); val[trieN]=fail[trieN]=0; tim[trieN]=0;s[trieN].clear(); return trieN; } void insert(const string & str,int k) { int cur=0; for(int i=0; i<str.size(); i++) { int d=str[i]-'a'; if(!ch[cur][d]) { ch[cur][d]=newnod(); } cur=ch[cur][d]; } val[cur]++; s[cur].push_back(k); } void build() { queue<int> q; for(int i=0; i<maxm; i++) { if(ch[0][i]) { q.push(ch[0][i]); } } // q.push(0); while(!q.empty()) { int cur=q.front(); q.pop(); for(int i=0; i<maxm; i++) { if(ch[cur][i]) { // cout<<cur<<' '<<i<<endl; //cout<<fail[cur]<<'\n'; fail[ch[cur][i]]=ch[fail[cur]][i]; in[fail[ch[cur][i]]]++; //cout<<fail[ch[cur][i]]<<"INNNNN"<<'\n'; q.push(ch[cur][i]); } else { ch[cur][i]=ch[fail[cur]][i]; } } } } //vector<int>ans; //int man=0; void topu() { queue<int>q; /*for(int i=1;i<=trieN;i++){ cout<<i<<"IN"<<in[i]<<'\n'; }*/ for(int i=0;i<=trieN;i++){ if(in[i]==0){ q.push(i);}} while(!q.empty()){ int x=q.front(); //cout<<x<<" "<<ans[x]<<'\n'; q.pop(); if(val[x]){ for(int i=0;i<s[x].size();i++) tim[s[x][i]]=ans[x]; } int y=fail[x]; ans[y]+=ans[x]; in[y]--; if(in[y]==0)q.push(y); } } void query(const string & str) { int res=0,cur=0; for(int i=0; str[i]; i++) { int d=str[i]-'a'; cur=ch[cur][d]; ans[cur]++; } } } ac; //string A[maxn]; int main() { string s; int n; while(scanf("%d",&n)!=EOF) { ac.init(); //if(n==0)break; for(int i=0; i<n; i++) { cin>>s; ac.insert(s,i); } ac.build(); cin>>s; ac.query(s); ac.topu(); for(int i=0;i<n;i++){ cout<<ac.tim[i]<<'\n'; } } }