hdu2222--Keywords Search+AC自动机模板

来源:互联网 发布:mysql字段名大小写 编辑:程序博客网 时间:2024/06/08 09:25

题目链接:点击进入
KMP对模式串进行处理,然后就可以方便的判断模式串是否在目标串中出现了;这显示适合一个模式串多个目标串的情况。但是如果模式串有多个,这时如果还用KMP则需要对每个串都进行一次处理,显然不是很合适。其实这时候可以将所有模式串建成一棵trie树,然后采用类似于kmp的方法计算出failed指针,也就可以方便的进行匹配了。其实这就是ac自动机的思想。

代码如下:

#include<iostream>#include<cstdio>#include<cstring>#include<queue>using namespace std;const int maxn=500000+100;struct Trie{    ///next数组表示的就是trie树    ///fail数组记录了每个节点的失败指针    ///end数组记录了以当前节点作为结尾的字符串的个数    int next[maxn][26],fail[maxn],end[maxn];    ///root表示trie的根节点,L表示当前trie的节点总数    int root,L;    int newnode()    {        for(int i=0;i<26;i++)          next[L][i]=-1;        end[L++]=0;        return L-1;    }    void init()    {        L=0;        root=newnode();    }    void insert(char buf[])    {        int len=strlen(buf);        int now=root;        for(int i=0;i<len;i++)        {            if(next[now][buf[i]-'a']==-1)              next[now][buf[i]-'a']=newnode();            now=next[now][buf[i]-'a'];        }        end[now]++;    }   ///采用bfs形式构造fail指针    void build()    {        queue<int>Q;        fail[root]=root;        for(int i=0;i<26;i++)        {            ///如果当前节点的第i个儿子不存在            ///则将其补上,为当前节点失败节点的第i个儿子           if(next[root][i]==-1)              next[root][i]=root;           else           {               fail[next[root][i]]=root;               Q.push(next[root][i]);           }        }        while(!Q.empty())        {            int now=Q.front();            Q.pop();            for(int i=0;i<26;i++)            {                if(next[now][i]==-1)                   next[now][i]=next[fail[now]][i];                else                {                    fail[next[now][i]]=next[fail[now]][i];                    Q.push(next[now][i]);                }            }        }    }    int query(char buf[])    {        int len=strlen(buf);        int res=0;        int now=root;        for(int i=0;i<len;i++)        {            now=next[now][buf[i]-'a'];            int temp=now;            while(temp != root)            {                res+=end[temp];                end[temp]=0;                temp=fail[temp];            }        }        return res;    }};char str[maxn*2];Trie ac;int main(){   int T;   int n;   scanf("%d",&T);   while(T--)   {       scanf("%d",&n);       ac.init();       for(int i=0;i<n;i++)       {           scanf("%s",str);           ac.insert(str);       }       ac.build();       scanf("%s",str);       printf("%d\n",ac.query(str));   }  return 0;}
1 0