HDU 2222  AC自动机模板题

1、HDU 2222

2、题意:给出n个单词,一个字串,求有多少个单词在字串里出现了。注意给出的单词可能会重复,重复的不计。

3、总结:入门题。在查询这里还是不太懂。

// 2222
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define F(i,a,b)  for (int i=a;i<b;i++)
#define FF(i,a,b) for (int i=a;i<=b;i++)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
typedef long long ll;
const int N = 1e6+10;

struct node
{
    int count;
    node *next[26];
    node *fail;
    void init() {    //初始化 
        mes(next,NULL);
        count=0;
        fail=NULL;
    }
}*q[500010];
node *root;
int head,tail;
char str[N];

void insert(char *keyword)
{
    int len=strlen(keyword);
    node *p=root;
    for(int i=0; i<len; i++) {
        int index=keyword[i]-'a';
        if(p->next[index]==NULL)  p->next[index]=new node();    //注:这里要new申请内存,不要忘了 
        p=p->next[index];
    }
    p->count++;
}

void build_ac_automation()    //初始化fail指针,BFS
{
    q[tail++]=root; 
    while(head!=tail) {
        node *p=q[head++];    //弹出队头
        node *temp=NULL;
        for(int i=0; i<26; i++) {
            if(p->next[i]!=NULL) {
                if(p==root)    p->next[i]->fail=root;    //第一个元素fail必指向根
                else {
                    temp=p->fail;
                    while(temp) {    //2种情况结束:匹配为空or找到匹配
                        if(temp->next[i]) {        //找到匹配
                            p->next[i]->fail=temp->next[i];    
                            break;
                        }
                        temp=temp->fail;
                    }
                    if(!temp) p->next[i]->fail=root;     //为空则从头匹配
                }
                q[tail++]=p->next[i];    //入队
            }
        }
    }
}

void query()        //扫描,查询这里还是没太搞懂 
{
    int i=0,cnt=0,index,len=strlen(str);
    node *p=root;
    for(int i=0; str[i]; i++) {
        index=str[i]-'a';
        while(p->next[index]==NULL&&p!=root)  p=p->fail;    //跳转失败指针
        p=p->next[index];
        if(p==NULL)  p=root;
        node *temp=p;    //p即是找到的当前结点,p不动,temp计算后缀串
        while(temp!=root&&temp->count!=-1) {
            cnt+=temp->count;
            temp->count=-1;
            temp=temp->fail;
        }
    }
    printf("%d\n", cnt);
}

int main()
{
    int T,n;
    char keyword[100];
    scanf("%d", &T);
    while(T--) {
        head=tail=0;
        scanf("%d", &n);
        getchar();
        root=new node();
        while(n--) {
            gets(keyword);
            insert(keyword);
        }
        build_ac_automation();
        gets(str);
        query();
    }

    return 0;
}
View Code
posted @ 2016-11-10 15:31  v9fly  阅读(156)  评论(0编辑  收藏  举报