Hdu 2896 病毒侵袭

依然是AC自动机模板题

注意ASCII码可见字符包括空格应该都能一次敲过去?

#include<bits/stdc++.h>
using namespace std;

const int maxn = 112345,maxLen = 130;

int toid(char c){ return c; }

queue<int> Q;

struct ACMA{
    int nex[maxn][maxLen],fail[maxn];
    int cnt[maxn];
    int _cnt,root;
    int newNode(){
        memset(nex[_cnt],cnt[_cnt] = fail[_cnt] = -1,sizeof(nex[_cnt]));
        return _cnt++;
    }
    void init(){
        _cnt = 0;
        root = newNode();
    }
    void insert(char *arr,int id){
        int st = root;
        for(int i=0;arr[i];i++){
            int & stx = nex[st][toid(arr[i])]; 
            if(stx == -1) stx = newNode();
            st = stx;
        }
        cnt[st] = id;
    }
    void build(){
        while(Q.empty()==false) Q.pop();
        fail[root] = root;
        int st;
        for(int i=0;i<maxLen;i++){
            if((st = nex[root][i]) != -1){
                fail[st] = root;
                Q.push(st);
            }
        }
        while(Q.empty()==false){
            st = Q.front(),Q.pop();
            for(int i=0;i<maxLen;i++){
                if(nex[st][i] != -1){
                    int fst = fail[st],son = nex[st][i];
                    while(fst != root && nex[fst][i] == -1)
                        fst = fail[fst];
                    fail[son] = nex[fst][i] == -1 ? root : nex[fst][i]; 
                    Q.push(son);
                }
                else{
                    nex[st][i] = nex[fail[st]][i];
                }
            }
        };
    }
    void out(){
        for(int i=0;i<_cnt;i++){
            printf("%d  ",i);
            printf("fail = %2d cnt = %d ",fail[i],cnt[i]);
            for(int j=0;j<26;j++){
                if(nex[i][j] != -1)
                printf("(%c:%3d)",j+'a',nex[i][j]);
            }
            puts("");
        }
    }
    int cal(char *arr,int * anw){
        int len = 0, st = root;
        for(int i=0;arr[i];i++){
            st = nex[st][toid(arr[i])];
            int tem = st;
            while(tem != root){
                if(cnt[tem] != -1)
                    anw[len++] = cnt[tem];
                tem = fail[tem];
            }
            if(len == 3) break;
        }
        return len;
    }
}acma;

int anw[5];

bool solve(char *arr,int id){
    int len = acma.cal(arr,anw);
    if(len != 0){
        sort(anw,anw+len);
        printf("web %d:",id);
        for(int i=0;i<len;i++){
            printf(" %d",anw[i]);
        }
        puts("");
        return true;
    }
    return false;
}

char arr[maxn];
int main(){
    int n;
    while(~scanf("%d\n",&n)){
        acma.init();
        for(int i=1;i<=n;i++){
            gets(arr);
            acma.insert(arr,i);
        }
        acma.build();
        scanf("%d\n",&n);
        int cnt = 0;
        for(int i=1;i<=n;i++){
            gets(arr);
            cnt += solve(arr,i);
        }
        printf("total: %d\n",cnt);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值