AC自动机

来源:互联网 发布:天刀捏脸数据金木研 编辑:程序博客网 时间:2024/06/15 17:32

现在来讲,我对AC自动机的理解,就是说,建一棵TRIE树,然后利用BFS遵循每次找到到根的路径上的一个节点,该节点的儿子中有该字符,就把fail指针赋给它。读入就是建trie树,query比较烦,还需理解。明天的目标是彻底搞懂AC自动机,然后复习一下splay和树链剖分,然后A两道题库题后,巩固AC自动机

#include<cstdio>#include<queue>#include<iostream>#include<algorithm>#include<cstring>using namespace std;int t,n;char st[100001];struct AK_automic_machine{    int en[1000001],son[1000001][26],fail[1000001],end[1000001],root,S;    int newnode()    {        S++;        for(int i=0;i<=25;i++) son[S][i]=-1;        end[S]=0;        return S;    }    void clear()    {        S=0;        root=newnode();    }    void add(char *s)    {        int len=strlen(s);        int p=root;        for(int i=0;i<len;i++)        {            if(son[p][s[i]-'a']==-1)             {                son[p][s[i]-'a']=newnode();            }            p=son[p][s[i]-'a'];        }        end[p]++;    }    void build()    {        queue<int>q;        fail[root]=root;        for(int i=0;i<=25;i++)         if(son[root][i]!=-1)         {            fail[son[root][i]]=root;q.push(son[root][i]);        }        else son[root][i]=root;        while(!q.empty())        {            int node=q.front();q.pop();            for(int i=0;i<=25;i++)            {                if(son[node][i]==-1)                 {                    son[node][i]=son[fail[node]][i];                }                else                {                    fail[son[node][i]]=son[fail[node]][i];                    q.push(son[node][i]);                }            }        }    }    int query(char *s)    {        int len=strlen(s);        int ans=0;        int p=root;        int tmp;        for(int i=0;i<len;++i)        {            p=son[p][s[i]-'a'];            tmp=p;            while(tmp!=root)            {                ans+=end[tmp];                end[tmp]=0;                tmp=fail[tmp];            }        }        return ans;    }}AC;int main(){    scanf("%d",&t);    while(t--)    {        AC.clear();        scanf("%d",&n);        for(int i=1;i<=n;i++)        {            scanf("%s",st);AC.add(st);        }        scanf("%s",st);        AC.build();        printf("%d",AC.query(st));    }}

HDU2222冥冥懂了AC自动机的原理,代码能力太弱,写不出来,明天继续研究!

#include<cstdio>#include<queue>#include<iostream>#include<algorithm>#include<cstring>#include<cstdlib>using namespace std;int t,n;char st[1001001];struct AK_automic_machine{    int son[501001][28],fail[501001],end[501001],root,S;    int newnode()    {        S++;        for(int i=0;i<26;i++) son[S][i]=-1;        end[S]=0;        return S;    }    void clear()    {        S=0;        root=newnode();    }    void add(char *s)    {        int i,len=strlen(s);        int p=root;        for(i=0;i<len;i++)        {            if(son[p][s[i]-'a']==-1)             {                son[p][s[i]-'a']=newnode();            }            p=son[p][s[i]-'a'];        }        end[p]++;    }    void build()    {        fail[root]=root;        queue<int>q;        for(int i=0;i<26;i++)         if(son[root][i]==-1) son[root][i]=root;        else{fail[son[root][i]]=root;q.push(son[root][i]);}        while(!q.empty())        {            int node=q.front();q.pop();            for(int i=0;i<=25;i++)            {                if(son[node][i]==-1)                 {                    son[node][i]=son[fail[node]][i];                }                else                {                    fail[son[node][i]]=son[fail[node]][i];                    q.push(son[node][i]);                }            }        }    }    int query(char *s)    {        int len=strlen(s);        int ans=0;        int p=root;        for(int i=0;i<len;++i)        {            p=son[p][s[i]-'a'];            int tmp=p;            while(tmp!=root)            {            ans+=end[tmp];            end[tmp]=0;tmp=fail[tmp];            }        }        return ans;    }}AC;int main(){    scanf("%d",&t);    while(t--)    {        AC.clear();        scanf("%d",&n);        while(n--)        {            scanf("%s",st);            AC.add(st);        }        AC.build();        scanf("%s",st);        printf("%d\n",AC.query(st));    }    return 0;}