病毒侵袭 HDU - 2896(AC自动机)

题意:

给出若干个病毒串,不超过500个,每个病毒串长度在20~200之间。现在有若干个网站的原代码,要检测其中是否包含病毒,网站的个数不超过1000个,每个网站的原代码长度在7000-10000之间。已经如果包含病毒,最多包含3个病毒。输出每个含病毒网站包含的病毒的编号等信息,最后输出含病毒网站的个数。


AC自动机水题

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define rint register int
struct AC{
    int nxt[210*500][128],fail[210*500],id[210*500];
    int vis[210*500],ans[550];
    int sz;
    void Init(){
        for(rint i=0;i<=sz;i++){
            fail[i] = id[i] = 0;
            for(rint j=0;j<128;j++)
                nxt[i][j] = 0;
        }
        sz = 0;
    }
    void Insert(char *s,int k){
        int root = 0,len = strlen(s);
        for(rint i=0;i<len;i++){
            if(!nxt[root][s[i]]) nxt[root][s[i]] = ++sz;
            root = nxt[root][s[i]];
        }
        id[root] = k;
    }
    void Build(){
        queue<int> q;
        for(rint i=0;i<128;i++)
            if(nxt[0][i])
                q.push(nxt[0][i]);
        while(!q.empty()){
            int u = q.front();
            q.pop();
            for(rint i=0;i<128;i++){
                if(nxt[u][i]){
                    fail[nxt[u][i]] = nxt[fail[u]][i];
                    q.push(nxt[u][i]);
                }
                else nxt[u][i] = nxt[fail[u]][i];
            }
        }
    }
    bool Query(char *s,int num){
        int root = 0,len = strlen(s);
        memset(vis,0,sizeof(vis));
        int ok = 0,k = 0;
        for(rint i=0;i<len;i++){
            if(!nxt[root][s[i]]) continue;
            root = nxt[root][s[i]];
            int tmp = root;
            while(tmp && !vis[tmp]){
                vis[tmp] = 1;
                if(id[tmp]) ans[++k] = id[tmp],ok = 1;
                tmp = fail[tmp];
            }
        }
        if(!ok) return false;
        printf("web %d:",num);
        sort(ans+1,ans+k+1);
        for(rint i=1;i<=k;i++) printf(" %d",ans[i]);
        printf("\n");
        return true;
    }
}ac;
char S[10005],T[10005];
int main(){
    int n,m;
    while(~scanf("%d",&n)){
        getchar();
        ac.Init();
        for(rint i=1;i<=n;i++){
            gets(S);
            ac.Insert(S,i);
        }
        ac.Build();
        scanf("%d",&m);
        getchar();
        int res = 0;
        for(rint i=1;i<=m;i++){
            gets(T);
            if(ac.Query(T,i))
                res++;
        }
        printf("total: %d\n",res);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值