HDU 2222 Keywords Search AC自动机模板题

  题意:给你一些单词和一个句子,问有多少个单词在这个句子上出现过。

  AC自动机裸题

  

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>

using namespace std;

const int maxn = 1000001;
queue <int> q;
struct Tree
{
    int ch[maxn][28], fail[maxn], count[maxn], tot, root;
    void clear()
    {
        root = tot = 0;
        memset(ch, -1, sizeof(ch));
        memset(fail, -1, sizeof(fail));
        memset(count, 0, sizeof(count));
    }
    void insert(char *str)
    {
        int x = root, len = strlen(str+1);
        for (int i = 1; i <= len; ++i)
        {
            int id = str[i]-'a';
            if (ch[x][id] == -1)
                ch[x][id] = ++tot;
            x = ch[x][id];
        }
        count[x] ++;
    }
    void build()
    {
        q.push(root);
        while (!q.empty())
        {
            int x = q.front();
            q.pop();
            for (int i = 0; i < 26; ++i)
                if (ch[x][i] != -1)
                {
                    if (x == root)
                        fail[ch[x][i]] = root;
                    else
                    {
                        int y = fail[x];
                        while (y != -1)
                        {
                            if (ch[y][i] != -1)
                            {
                                fail[ch[x][i]] = ch[y][i];
                                break ;
                            }
                            y = fail[y];
                            
                        }
                        if (y == -1)
                            fail[ch[x][i]] = root;
                    }
                    q.push(ch[x][i]);
                }
        }
    }
    int find(char *str)
    {
        int x = root, len = strlen(str+1), ret = 0;
        for (int i = 1; i <= len; ++i)
        {
            int id = str[i]-'a';
            while (ch[x][id] == -1 && x != root)
                x = fail[x];
            x = ch[x][id];
            if (x == -1)
                x = root;
            int y = x;
            while (y != root && count[y] != -1)
            {
                ret += count[y];
                count[y] = -1;
                y = fail[y];
            }
        }
        return ret;
    }
}T;
int n;
char str[maxn];

int main()
{
    int Case;
    scanf("%d", &Case);
    while (Case --)
    {
        T.clear();
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i)
        {
            scanf("%s", str+1);
            T.insert(str);    
        }
        T.build();
        scanf("%s", str+1);
        printf("%d\n", T.find(str));
    }
    return 0;
}

 

posted @ 2017-02-17 20:46  Splay  阅读(238)  评论(0编辑  收藏  举报