随笔 - 11, 文章 - 0, 评论 - 12, 引用 - 0
数据加载中……

hdu 2222 Keywords Search 典型的AC自动机入门题目

前段时间学会了trie树之后,今天终于学习了一下AC自动机,这个还是挺难学的,现在我还是有点不太懂,参照了网上的代码才把这道题给A了。
让我自己背着写出来还不一定会写。这里有一篇比较好的介绍AC自动机的文章http://www.cppblog.com/mythit/archive/2009/04/21/80633.html
先看一下这道题吧,大意是给我们一部字典和一个模式串,让我们求出字典中有多少个单词在模式串的子串,开始一直TLE,我都郁闷了,最后让acmost
看了一下,他让我把 for (int i = 0 ;i < strle(s); i++) 里面的strlen(s)改一下试试,我改为了s[i],果然一下就过了,原来每次都计算strlen(s)会增加复杂度,太菜了
帖下代码:
  

  1#include<iostream>
  2#include<queue>
  3using namespace std;
  4
  5struct node{
  6    int isword;
  7    node *fail;
  8    node *next[26];
  9    void init(){
 10        isword=0;
 11        fail=0;
 12        memset(next,0,sizeof(next));
 13    }

 14}
;
 15
 16node set[500000];
 17node *root;
 18int cot;
 19char ch[1000005];
 20
 21void insert(char s[])
 22{
 23    if(!root){
 24        set[cot].init();
 25        root=&set[cot++];
 26    }

 27    node *pos=root;
 28    for(int i=0;s[i];i++){
 29        int k=s[i]-'a';
 30        if(!pos->next[k]){
 31            set[cot].init();
 32            pos->next[k]=&set[cot++];
 33            pos=pos->next[k];
 34        }

 35        else pos=pos->next[k];
 36    }

 37    pos->isword++;
 38}

 39void input()
 40{
 41    int n;
 42    char s[55];
 43    scanf("%d",&n);
 44    for(int i=1;i<=n;i++){
 45        scanf("%s",s);
 46        insert(s);
 47    }

 48    scanf("%s",ch);
 49}

 50
 51void build_ac()
 52{
 53    queue<node *> myque;
 54    myque.push(root);
 55    while(!myque.empty()){
 56        node *tp=myque.front();
 57        myque.pop();
 58        for(int i=0;i<26;i++){
 59            if(tp->next[i]){
 60                if(tp==root)
 61                    tp->next[i]->fail=root;
 62                else{
 63                    node *pos=tp->fail;
 64                    while(pos){
 65                        if(pos->next[i]){
 66                            tp->next[i]->fail=pos->next[i];
 67                            break;
 68                        }

 69                        pos=pos->fail;
 70                    }

 71                    if(pos==0) tp->next[i]->fail=root;
 72                }

 73                myque.push(tp->next[i]);
 74            }

 75        }

 76    }

 77}

 78
 79int query()
 80{
 81    int ans=0;
 82    node *tp=root;
 83    for(int i=0;ch[i];i++){
 84        int k=ch[i]-'a';
 85        if(tp->next[k])
 86            tp=tp->next[k];
 87        else{
 88            while(tp!=root&&!tp->next[k])
 89                tp=tp->fail;
 90            if(!tp->next[k]) tp=root;
 91            else tp=tp->next[k];
 92        }

 93        node *pos=tp;
 94        while(pos!=root&&pos->isword>=0){
 95            ans+=pos->isword;
 96            pos->isword=-1;
 97            pos=pos->fail;
 98        }

 99    }

100    return ans;
101}

102int main()
103{
104    int t;
105    scanf("%d",&t);
106    while(t--){
107        root=0;
108        cot=0;
109        input();
110        build_ac();
111        int ans=query();
112        printf("%d\n",ans);
113    }

114    return 0;
115}

116

posted on 2010-04-17 21:59 acleast 阅读(354) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理