HDU2222 AC自动机 入门模板

来源:互联网 发布:股海网指标公式源码 编辑:程序博客网 时间:2024/05/21 03:56

HDU 222 Keywords Search
AC 自动机入门模板题
调了一下午
因为输入最后一个字符串打成了%d还有两处取反符号打错 WA了无数次

血泪史 以后要注意
Vjudge 炸崩

AC自动机思路:
这个算法的目的:用几个给定的模式串去在一个串 T 中匹配
简单概括实现方式:
1.对所有的模式串建Trie树。
Trie树
2.从根节点开始建立Fail指针。基本的逻辑如下:

buildFail(node root){    root->fail=NULL //将root的fail指针指向空节点    将root压入队列    node now    node temp // 用于临时存储递归寻找下一个可能的Fail节点    while 队列不为空    now=队列最前节点    for i 1 to 26 // 找 a-z 26个字母        if now节点下有i这个数字对应的字母            if 如果now是root节点                 then do now下该数字的节点的Fail指向root            else                 temp=now的fail指向的节点                while temp 不为空节点 //如果temp为空节点 即代表以及找回到了root                    if temp节点下存在有i这个数字对应的字母                        then do                         now下该数字的节点的Fail指向temp节点下i这个数字对应的字母的节点                        终止while循环                    else temp=temp的fail指向的节点 //继续寻找 直到下次匹配成功                if while循环结束后 temp是空节点//如果temp为空节点 即代表以及找回到了root都没有找到匹配                    then do now下该数字的节点的Fail指向root            将now节点下i这个数字对应的字母的节点压入队列        else continue}

3.匹配过程:看代码吧= = = = = = = = =

#include<queue>#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>using namespace std;int T,n;class Trie{    public:        int cnt;        Trie * nxt[26],* fail;        Trie() { cnt=0; fail=NULL;  memset(nxt,0,sizeof nxt); }};inline int getID(char t) {return t-'a';}int len,id;Trie *p;void insertTrie(char * pat,Trie * root){    len=strlen(pat);p=root;    for(register int i=0;i<len;i++)    {        id=getID(pat[i]);        if(!p->nxt[id]) p->nxt[id]=new Trie() ;        p=p->nxt[id];    }    p->cnt++;    return ;}queue<Trie *> q;Trie * temp;void buildFail(Trie * root){    root->fail=NULL;    q.push(root);    while(!q.empty())    {        p=NULL;        temp=q.front();q.pop();        for(register int i=0;i<26;i++)            if(temp->nxt[i])            {                if(temp==root) temp->nxt[i]->fail=root;                else                 {                    p=temp->fail;                    while(p)                    {                        if(p->nxt[i]) { temp->nxt[i]->fail=p->nxt[i] ; break; }                        p=p->fail;                    }                    if(!p) temp->nxt[i]->fail=root;                }                q.push(temp->nxt[i]);            }       }    return ;}int ans=0;int acMatch(char * str,Trie * root){    ans=0;    len=strlen(str);p=root;    for(register int i=0;i<len;i++)    {        id=getID(str[i]);        while(!p->nxt[id]&&p!=root) p=p->fail;        p=p->nxt[id];        if(p==NULL) p=root;        temp=p;        while(temp!=root&&temp->cnt!=-1)        {            ans+=temp->cnt;            temp->cnt=-1;            temp=temp->fail;        }    }    return ans;}void dataIn(){    char buf[1000005];    scanf("%d",&T);    while(T--)    {        Trie *root=new Trie();        scanf("%d",&n);        for(register int i=1;i<=n;i++)        {            scanf("%s",buf);            insertTrie(buf,root);        }        buildFail(root);        scanf("%s",buf);        printf("%d\n",acMatch(buf,root));    }}int main(){    dataIn();    return 0;}
原创粉丝点击