首页 > 代码库 > HDU 2222 Keyword Search AC自动机模板

HDU 2222 Keyword Search AC自动机模板

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <ctime>
#include <iomanip>

#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-6)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 0x3f3f3f3f
#define Mod 20071027

using namespace std;

const int MAXN = 26;

struct N
{
    int next[MAXN],fail,flag;
}st[500010];

bool vis[500010];

int Top;

int creat()
{
    memset(st[Top].next,-1,sizeof(st[Top].next));
    st[Top].fail = -1,st[Top].flag = 0;
    return Top++;
}

char s[1000010];

inline int sel(char tar)
{
    return (tar-'a');
}

int Get_Fail(int site,int tar)
{
    while(1)
    {
        if(site == -1)
            return 0;
        if(st[site].next[tar] != -1)
            return st[site].next[tar];
        site = st[site].fail;
    }
}

queue<int> q;

void Get_Fail(int root)
{
    st[root].fail = -1;

    q.push(root);

    int f;

    while(q.empty() == false)
    {
        f = q.front();
        q.pop();

        for(int i = 0; i < MAXN; ++i)
        {
            if(st[f].next[i] != -1)
            {
                st[st[f].next[i]].fail = Get_Fail(st[f].fail,i);
                q.push(st[f].next[i]);
            }
        }
    }
}

//pre记录当前的节点的父节点,为了寻找fail指针
void Get_Trie(int root,char *s,int site)
{
    while(s[site] != '\0')
    {
        if(st[root].next[sel(s[site])] == -1)
            st[root].next[sel(s[site])] = creat();
        root = st[root].next[sel(s[site])];
        ++site;
    }
    
    st[root].flag++;
}

int Match(int root,char *s,int site)
{
    int ans = 0,p = root,tmp;

    for(site = 1; s[site] != '\0' ; ++site)
    {
        while(p != -1 && st[p].next[sel(s[site])] == -1)
            p = st[p].fail;

        if(p == -1)
        {
            p = root;
            continue;
        }
        p = st[p].next[sel(s[site])];

        tmp = p;

        while(tmp != root && st[tmp].flag != -1)
        {
            if(st[tmp].flag)
            {
                ans += st[tmp].flag;
                st[tmp].flag = -1;
            }
            tmp = st[tmp].fail;
        }
    }
    return ans;
}

int main()
{
    int T;
    scanf("%d",&T);

    int n,root,i;

    while(T--)
    {
        Top = 0;
        root = creat();

        scanf("%d",&n);

        for(i = 1; i <= n; ++i)
        {
            scanf("%s",s+1);
            Get_Trie(root,s,1);
        }

        Get_Fail(root);

        scanf("%s",s+1);

        printf("%d\n",Match(root,s,1));
    }

    return 0;
}