HDU2222 - Keywords Search - AC自动机

本文详细介绍了如何使用AC自动机解决字符串匹配问题,包括构建AC自动机、插入模式串及查询匹配串等步骤。适用于需要高效处理大量模式串匹配场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

分类data structures strings

1.题意概述

  • 给你N(N <= 10000)个模式串和一个待匹配串,现在问你待匹配串中出现过几种模式串?

2.解题思路

  • 裸的AC自动机,因为问的是出现过几次,所以标记策略是每一类的最后一个位置置1,Query时候访问过一个种类就注意置0!

3.AC代码

class Trie {
public:
#define tot_len 500010
#define tot_ch 26
#define CUR (s[i] - 'a')
    int next[tot_len][tot_ch], fail[tot_len], end[tot_len];
    int root, L;

    int Newnode() {
        rep(i, 0, tot_ch) next[L][i] = -1;
        end[L++] = 0;
        return L - 1;
    }

    void Init() {
        L = 0;
        root = Newnode();
    }

    void Insert(char *s, int val) {
        int len = strlen(s);
        int now = root;
        rep(i, 0, len) {
            if (next[now][CUR] == -1)
                next[now][CUR] = Newnode();
            now = next[now][CUR];
        }
        end[now] += val;
    }

    void Build() {
        queue<int> q;
        fail[root] = root;
        rep(i, 0, tot_ch) {
            if (next[root][i] == -1)
                next[root][i] = root;
            else {
                fail[next[root][i]] = root;
                q.push(next[root][i]);
            }
        }
        while (!q.empty()) {
            int now = q.front();
            q.pop();
            rep(i, 0, tot_ch) {
                if (next[now][i] == -1)
                    next[now][i] = next[fail[now]][i];
                else {
                    fail[next[now][i]] = next[fail[now]][i];
                    q.push(next[now][i]);
                }
            }
        }
    }

    int Query(char *s) {
        int len = strlen(s);
        int now = root, ans = 0;
        rep(i, 0, len) {
            now = next[now][CUR];
            for (int j = now; j != root && end[j]; j = fail[j]) {
                ans += end[j];
                end[j] = 0;
            }
        }
        return ans;
    }
#undef CUR
#undef tot_ch
#undef tot_len
} AC;
char ch[maxn], key[51];
inline void solve() {
    int t, n;
    scanf("%d", &t);
    while (t--) {
        AC.Init();
        scanf("%d", &n);
        rep(i, 0, n) {
            scanf("%s", key);
            AC.Insert(key, 1);
        }
        AC.Build();
        scanf("%s", ch);
        printf("%d\n", AC.Query(ch));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值