HDU 2222 AC自动机 入门题

本文介绍了一个AC自动机的实现案例,包括插入字符串、获取失败指针及搜索算法等核心功能,并通过具体代码展示了AC自动机的工作原理。

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

题目链接

第一次写AC自动机……

代码如下:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#define sf scanf
#define pf printf
using namespace std;
const int sigma_size = 26;
struct Trie_Node{
    int value;//单词节点计数 其他为0
    struct Trie_Node* next[sigma_size];
    struct Trie_Node* fail;//失配跳转指针  没有最大前后缀则为root
    char ch;
};

typedef struct Trie_Node* poi_node;
poi_node root;
poi_node make_node(char ch){
    poi_node node = new Trie_Node;
    node -> value = 0;
    node -> fail = NULL;
    node -> ch = ch;
    for(int i = 0;i < sigma_size;++i){
        node -> next[i] = NULL;
    }
    return node;
}
void Insert(char* s){
    int len = strlen(s);
    poi_node cur = root;
    for(int i = 0;i < len;++i){
        int idx = s[i] - 'a';
        if(cur -> next[idx] == NULL){
            cur -> next[idx] = make_node(idx + 'a');
        }
        cur = cur -> next[idx];
    }
    cur -> value++;
    return;
}

void get_fail(){
    queue<poi_node> q;
    q.push(root);
    while( !q.empty() ){
        poi_node cur = q.front();q.pop();
        for(int i = 0;i < sigma_size;++i){
            if(cur -> next[i]){
                poi_node p = cur -> fail;
                while(p && !p -> next[i]) p = p -> fail;

                cur -> next[i] -> fail = p ? p -> next[i] : root;
                q.push(cur -> next[i]);
            }
        }
    }
}

int Search(char* s){
    int len = strlen(s);
    int ans = 0;
    poi_node cur = root;
    for(int i = 0;i < len;++i){
        int idx = s[i] - 'a';
        if(cur -> next[idx] == NULL){ //失配
            poi_node f = cur;
            while(f && !f -> next[idx]){
                f = f -> fail;
            }
            cur = f ? f -> next[idx] : root;
        }
        else cur = cur -> next[idx];
        ans += cur -> value;
        if(cur -> value > 0){
            cur -> value = 0;
            poi_node p = cur -> fail;
            while(p){
                ans += p -> value;
                p -> value = 0;
                p = p -> fail;
            }
        }
    }
    return ans;
}

void DFS(poi_node ROOT){
    for(int i = 0;i < sigma_size;++i){
        if(ROOT -> next[i] != NULL) DFS(ROOT->next[i]);
    }
    delete ROOT;
}
char word[60];
char line[1000000 + 5];
int main(){
    int T;
    sf("%d",&T);
    while(T--){
        root = make_node('#');
        int n;sf("%d",&n);
        for(int i = 0;i < n;++i){
            sf("%s",word);
            Insert(word);
        }
        sf("%s",line);
        get_fail();
        pf("%d\n",Search(line));
        DFS(root);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值