HDU2222:Keywords Search 题解

思路

这道题就是一道 AC 自动机的模板题。AC 自动机适用于多个模式串匹配的情景,实际上,它就是在 Trie 树上进行的一个匹配算法。这里有一篇很优秀的讲稿,不了解 AC 自动机的读者可以自行阅读:https://blog.csdn.net/creatorx/article/details/71100840

这道题我们只需要在 Trie 树上增加一个关键字 \(sum\) 即可。

代码

// HDU-2222.cpp
#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
struct node
{
    node *nxt[26], *fail;
    int sum;
    ~node()
    {
        for (int i = 0; i < 26; i++)
            if (nxt[i] != NULL)
                delete nxt[i];
    }
};
node *root;
int cnt;
char str[1000020];
void insert(string str)
{
    int siz = str.length();
    node *p = root;
    for (int i = 0; i < siz; i++)
    {
        int curt = str[i] - 'a';
        if (p->nxt[curt] == NULL)
        {
            p->nxt[curt] = new node();
            p->nxt[curt]->fail = NULL;
            for (int i = 0; i < 26; i++)
                p->nxt[curt]->nxt[i] = NULL;
            p->nxt[curt]->sum = 0;
        }
        p = p->nxt[curt];
    }
    p->sum++;
}
void build_AC_automation()
{
    queue<node *> q;
    q.push(root);
    node *p, *tmp;
    while (!q.empty())
    {
        tmp = q.front();
        q.pop();
        for (int i = 0; i < 26; i++)
            if (tmp->nxt[i])
            {
                if (tmp == root)
                    tmp->nxt[i]->fail = root;
                else
                {
                    p = tmp->fail;
                    while (p)
                        if (p->nxt[i])
                        {
                            tmp->nxt[i]->fail = p->nxt[i];
                            break;
                        }
                        else
                            p = p->fail;
                    if (p == NULL)
                        tmp->nxt[i]->fail = root;
                }
                q.push(tmp->nxt[i]);
            }
    }
}
void ac_automation(string passage)
{
    int siz = passage.length();
    node *p = root;
    for (int i = 0; i < siz; i++)
    {
        int curt = passage[i] - 'a';
        while (!p->nxt[curt] && p != root)
            p = p->fail;
        p = p->nxt[curt];
        if (p == NULL)
            p = root;
        node *tmp = p;
        while (tmp != root)
        {
            if (tmp->sum >= 0)
            {
                cnt += tmp->sum;
                tmp->sum = -1;
            }
            else
                break;
            tmp = tmp->fail;
        }
    }
}
int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        int n;
        scanf("%d", &n);
        root = new node();
        for (int i = 1; i <= n; i++)
            scanf("%s", str), insert(str);
        build_AC_automation();
        scanf("%s", str);
        ac_automation(str);
        printf("%d\n", cnt);
        cnt = 0;
    }
    return 0;
}

 

Leave a Reply

Your email address will not be published. Required fields are marked *