hdu 2222 Keywords Search AC自动机——多串匹配

http://acm.hdu.edu.cn/showproblem.php?pid=2222

题意:

给出n个单词,再给出一段包含m个字符的文章,求有多少个单词在文章里出现过。

思路:
才开开始以为简单的Trie数就可以,结果TLE到无语,字典树枚举每一个查找单词的第一个字母的话是O(N*50)前边还有一个T计算的话会超时,看了一下解题报告原来是AC自动机的基础应用。给出一个不错的链接http://blog.himdd.com/?p=2169 这里讲的很详细。

想不到,回校第一个题目竟然是4个2的题号,无语。。。。

//#pragma comment(linker,"/STACK:327680000,327680000")

#include <iostream>

#include <cstdio>

#include <cmath>

#include <vector>

#include <cstring>

#include <algorithm>

#include <string>

#include <set>

#include <functional>

#include <numeric>

#include <sstream>

#include <stack>

#include <map>

#include <queue>



#define CL(arr, val)    memset(arr, val, sizeof(arr))



#define lc l,m,rt<<1

#define rc m + 1,r,rt<<1|1

#define pi acos(-1.0)

#define ll long long

#define L(x)    (x) << 1

#define R(x)    (x) << 1 | 1

#define MID(l, r)   (l + r) >> 1

#define Min(x, y)   (x) < (y) ? (x) : (y)

#define Max(x, y)   (x) < (y) ? (y) : (x)

#define E(x)        (1 << (x))

#define iabs(x)     (x) < 0 ? -(x) : (x)

#define OUT(x)  printf("%I64d\n", x)

#define lowbit(x)   (x)&(-x)

#define Read()  freopen("din.txt", "r", stdin)

#define Write() freopen("dout.txt", "w", stdout);





#define M 57

#define N 1000007

using namespace std;



struct node

{

    node *fail;

    node *next[26];

    int cnt;

    void newnode()//生成节点

    {

        fail = NULL;

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

        {

            next[i] = NULL;

        }

        cnt = 0;

    }

};

class Ac_Automat

{

    node *q[N],H[N],*root;

    int fr,tl,t;

    public:

//    初始化

    void init()

    {

        fr = tl = 0;

        t = 0;

        H[t].newnode();

        root = &H[t++];

    }

//    插入单词

    void insert(char *s)

    {

        int i,k,len;

        len = strlen(s);

        node *p = root;

        for (i = 0; i < len; ++i)

        {

            k = s[i] - 'a';

            if (p->next[k] == NULL)

            {

                H[t].newnode();

                p->next[k] = &H[t++];

            }

            p = p->next[k];

        }

        p->cnt++;

    }

//    建立失败指针

    void build()

    {

        root->fail = NULL;

        q[tl] = root;



        while (fr <= tl)

        {

            node *tmp = q[fr++];

            node *p = NULL;

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

            {

                if (tmp->next[i])

                {

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

                    else

                    {

                        p = tmp->fail;

                        while (p != NULL)

                        {

                            if (p->next[i])

                            {

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

                                break;

                            }

                            p = p->fail;

                        }

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

                    }

                    q[++tl] = tmp->next[i];

                }

            }



        }

    }

//    查找

    int query(char *s)

    {

        int res = 0;

        node *p = root;

        int len = strlen(s);

        for (int i = 0; i < len; ++i)

        {

            int k = s[i] - 'a';

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



            p = p->next[k];

            if (p == NULL) p = root;

            node *tmp = p;

            while (tmp != root && tmp->cnt != -1)

            {

                res += tmp->cnt;

                tmp->cnt = - 1;

                tmp = tmp->fail;

            }

        }

        return res;

    }

}ac;



char ques[M],ans[N];



int n;



int main()

{

    int i;

    int T;

    scanf("%d",&T);

    while (T--)

    {

        ac.init();

        scanf("%d",&n);

        for (i = 0; i < n; ++i)

        {

            scanf("%s",ques);

            ac.insert(ques);

        }

        ac.build();

//        printf(">>>>\n");

        scanf("%s",ans);

//        printf("%s\n",ans);

        printf("%d\n",ac.query(ans));

    }

    return 0;

}

  

 

你可能感兴趣的:(search)