HDU - 2222 AC 自动机模板

AC自动机详解 资料链接  http://www.cppblog.com/mythit/archive/2009/04/21/80633.html




题意:给你一些单词,,让你统计出现文章中的单词数....

此算法较难,必须要懂得 字典树 , kmp 算法,,但是还是太难,,林神也说自己忘了,要我自己看....悲催...搞了好久了....还是不懂失败指针的用法...


模板代码: 

/*


这是第一次写AC自动机,字典树明白,kmp也明白,,可就是不理解

失败指针的用法,只有先放下了,等以后思想境界高了,再来解决吧 


*/


#include<iostream>

#include<cstdio>

#include<string>

using namespace std;

#define kind 26

#define manx 500009

struct node{  /// 字典树

    node *fail;  /// 失败指针 

    node *next[kind]; /// tire 每个节点的26个子节点(最多26个字母) 

    int count;   /// 是否为单词的最后一个节点 

    node(){      /// 构造函数初始化 

        fail=NULL;

        count=0;

        memset(next,0,sizeof(next));

    } 

}*q[manx];       /// 队列,方便使用bfs构造失败指针 


char keyword[51]; ///输入单词 

char str[manx<<1];/// 模式串 

int head,tail;    /// 队列头尾指针 


void insert(char*str,node*root){  

    node *p=root;

    int i=0,index;

    while(str[i]){   插尾法

        index = str[i]-'a';

        if(p->next[index]==NULL) p->next[index]=new node();

        p=p->next[index];

        i++;

    }

    p->count++;

}

void build_ac(node*root){   AC自动机算法

    root->fail=NULL;

    q[head++]=root;

    while(head!=tail){

        node *temp = q[tail++];

        node *p = NULL;

        for(int i=0;i<26;i++){

            if(temp->next[i] != NULL){

                if(temp==root) temp->next[i]->fail=root;

                else {

                    p = temp->fail;

                    while(p!=NULL){

                        if(p->next[i]!=NULL){

                            temp->next[i]->fail = p->next[i];

                            break;

                        }

                        p=p->fail;

                    }

                    if(p==NULL) temp->next[i]->fail=root;

                }

                q[head++] = temp->next[i];

            }

        }

    }

}


int query(node *root){   匹配查找串

    int i=0,cnt=0,index,len=strlen(str);

    node *p = root;

    while(str[i]){

        index = str[i] - 'a';

        while(p->next[index]==NULL && p!=root) p=p->fail;

        p = p->next[index];

        p = (p==NULL)?root:p;

        node *temp = p;

        while(temp != root && temp->count != -1){

            cnt += temp->count;

            temp -> count = -1;

            temp = temp->fail;

        }

        i++;

    }

    return cnt;

}


int main(){

    int n,t;

    scanf("%d",&t);

    while(t--){

        head=tail=0;

        node *root = new node();

        scanf("%d",&n);

        getchar();

        while(n--){

            gets(keyword);

            insert(keyword,root);

        }

        build_ac(root);

        scanf("%s",str);

        printf("%d\n",query(root));

    }

}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值