【AC自动机】统计单词出现个数-map版

来源:互联网 发布:画梁图软件 编辑:程序博客网 时间:2024/05/22 03:17
AC自动机有很多版本,但是上一个版本的话找字典树结点的儿子要for,暴力去for,这个很费时间,所有我们可以加map去优化。
#include<map>#include<queue>#include<cmath>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#define Maxchar 1000000#define Maxm 10000#define Maxn 50#define Maxs 26#define mes(x,y) memset(x,y,sizeof(x));#define mpy(x,y) memcpy(x,y,sizeof(x))#define INF 2147483647using namespace std;struct Tire{    int s,c[Maxs+1],fail;    void clear(){    s=fail=0;mes(c,-1);} }t[Maxn*Maxm+1];int T,tot,ans,n;char a[Maxchar+1];map<int, map<int,int> >qt;void bt(int root){    int x=root,len=strlen(a+1);    for(int i=1;i<=len;i++){        int y=a[i]-'a'+1;        if(t[x].c[y]==-1){        qt[x][++qt[x][0]]=y;            t[x].c[y]=++tot;            t[tot].clear();        }        x=t[x].c[y];    }    t[x].s++;}queue<int> q;void bfs(){int x,y,son;    q.push(0);    while(q.empty()==0){        int x=q.front();        for(int i=1;i<=qt[x][0];i++){        y=qt[x][i];            son=t[x].c[y];            if(x==0)t[son].fail=0;            else{                int j=t[x].fail;                while(j!=0&&t[j].c[y]==-1)j=t[j].fail;                t[son].fail=max(t[j].c[y],0);            }            q.push(son);         }        q.pop();    }}void solve(){    int x=0,len=strlen(a+1),j;    for(int i=1;i<=len;i++){        int y=a[i]-'a'+1;        while(x!=0&&t[x].c[y]==-1)x=t[x].fail;        x=t[x].c[y];        if(x==-1){x=0;continue;}        j=x;        while(t[j].s!=0){            ans+=t[j].s;             t[j].s=0;            j=t[j].fail;        }    }    printf("%d\n",ans);}int main(){    scanf("%d",&T);    while(T--){        ans=tot=0;        scanf("%d",&n);        t[0].clear();        qt.clear();        for(int i=1;i<=n;i++){            scanf("%s",a+1);            bt(0);        }        bfs();        scanf("%s",a+1);        solve();    }    return 0;}
 

查看原文:http://hz2016.tk/blog/?p=31