[kuangbin带你飞]专题17:B - 病毒侵袭(HDU2896)

本文介绍了一种使用AC自动机实现的病毒检测方法。通过构建AC自动机并设置失败指针,可以高效地在文本中查找多种病毒模式。程序读取病毒签名库,并对输入的文本进行扫描,输出发现的病毒编号。

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

原题

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;

const int MAXN = 128;
int num[3];



struct node {
    node *next[MAXN], *fail;
    int v, flag;
    node() {
        for(int i = 0; i < MAXN; i++) next[i] = NULL;
        fail = NULL;
        v = flag  = 0;
    }
}*root;

void insert(string s, int n) {
    int l = (int)s.length();
    node* p = root;
    for(int i = 0 ; i < l; i ++) {
        int id = (int)s[i];
        if(!p->next[id]) p->next[id] = new node();
        p = p->next[id];
    }
    p->v = n; //单词末尾标记病毒序号
}


void setfail() {
    queue<node*> q;
    q.push(root);

    while(!q.empty()) {
        node* now = q.front(); q.pop();
        node* p = now->fail;
        for(int i = 0 ; i < MAXN; i++) if(now->next[i]) {
            while(p && !p->next[i]) p = p->fail;
            now->next[i]->fail = p ? p->next[i] : root;
            q.push(now->next[i]);
        } 
    }
}


bool ac(string s, int idx) {
    int k = 0;
    int l = (int)s.length();
    node* now = root;
    for(int i = 0 ; i < l; i++) {
        int id = (int)s[i];
        while(now && !now->next[id]) now = now->fail;
        now = now ? now->next[id] : root;
        for(node* p = now; p; p = p->fail) if(p->v) {//找到病毒
            if(p->flag == idx) continue; //此种病毒已记录
            num[k++] = p->v;
            p->flag = idx;//表示已被记录

        } 
    }
    if(num[0]) return true;//存在病毒
    return false;
}

int main() {
    freopen("a.in", "r", stdin);
    ios::sync_with_stdio(false);
    int N; cin >> N;
    string s;
    root = new node();
    for(int i = 1; i <= N; i++) {
        cin >> s;
        insert(s, i);//插入时插入病毒序号
    }
    setfail();

    int cnt = 0;
    cin >> N;
    for(int i = 1; i <= N; i++) {
        string ss;
        cin >> ss;
        memset(num, 0, sizeof(num));
        if(ac(ss, i)) {
            cnt++;
            sort(num, num+3);
            cout << "web " << i << ": ";
            for(int j = 0; j < 3; j++) if(num[j]) cout << num[j] << " ";
            cout << endl;
        }
    }
    cout << "total: " << cnt << endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值