struct Aho_Corasick_automation{ static const int maxn=1e6+5; int trans[maxn][26],fail[maxn],end[maxn]; int root,cnt; inline int new_node(){ //fail指针不需要初始化,因为在bfs的时候他被更新 for(int i=0;i<26;i++)trans[cnt][i]=0; end[cnt]=0; return cnt++; } void ini(){ cnt=0; root=new_node(); } void extend(char*buf){ int len=(int)strlen(buf+1); int u=root; for(int i=1;i<=len;i++){ if(trans[u][buf[i]-'a']==0) trans[u][buf[i]-'a']=new_node(); u=trans[u][buf[i]-'a']; } end[u]++; } void get_fail(){ queue<int>q; q.push(root); while(!q.empty()){ int u=q.front();q.pop(); for(int i=0;i<26;i++){ if(trans[u][i]==0){ trans[u][i]=-abs(trans[fail[u]][i]);//采用负数来表示非树边。。 } else{ q.push(trans[u][i]); fail[trans[u][i]]=abs(trans[fail[u]][i]); if(u==root)fail[trans[u][i]]=root; } } } } int query(char*buf){//统计母串里面出现了几种子串 int len=(int)strlen(buf+1); int u=root ,ret=0; for(int i=1;i<=len;i++){ u=abs(trans[u][buf[i]-'a']); for(int p=u;p!=root;p=fail[p]){ if(end[p]==-1)break; ret+=end[p]; end[p]=-1;//为什么要搞-1呢?可以用来剪枝,预防这样的特殊数据-> aaaaaaaaaaa...... } } return ret; } void debug(){ for(int i=0;i<35;i++)printf(" "); for(int j=0;j<26;j++){ printf("%2c",j+'a'); } puts(""); for(int i=0;i<cnt;i++){ printf("id=%3d | fail=%3d | end=%3d | chi=[",i,fail[i],end[i]); for(int j=0;j<26;j++){ printf("%2d",trans[i][j]); } printf("]\n"); } } };