hihocoder Trie图(AC自动机)

代码:

#include <cstdio>
#include <cstring>
#include <queue>
#define MAXN 1000010
using namespace std;
int q[MAXN];
int ascii[256];
struct Trie{
    int child[MAXN][26],fail[MAXN];
    bool mark[MAXN];
    int root,L;
    int newnode(){
        for(int i=0;i<26;++i) child[L][i]=-1;
        mark[L++]=false;
        return L-1;
    }
    void init(){
        L=0;
        root=newnode();
    }
    void insertnode(const char* str){
        int len=strlen(str);
        int now=root;
        for(int i=0;i<len;++i){
            if(child[now][ascii[str[i]]]==-1)
                child[now][ascii[str[i]]]=newnode();
            now=child[now][ascii[str[i]]];
        }
        mark[now]=true;
    }
    void build(){
        fail[root]=root;
        int top,tail;
        top=tail=0;
        for(int i=0;i<26;++i){
            if(child[root][i]==-1)
                child[root][i]=root;
            else{
                fail[child[root][i]]=root;
                q[tail++]=child[root][i];
            }
        }
        while(top<tail){
            int now=q[top++];
            if(mark[fail[now]])///优化1,不然超时
                mark[now]=true;
            for(int i=0;i<26;++i){
                if(child[now][i]==-1)
                    child[now][i]=child[fail[now]][i];
                else{
                    fail[child[now][i]]=child[fail[now]][i];
                    q[tail++]=child[now][i];
                }
            }
        }
    }
    bool query(const char* str){
        int len=strlen(str);
        int now=root;
        for(int i=0;i<len;++i){
            now=child[now][ascii[str[i]]];
            if(mark[now]) return true;
        }
        return false;
    }
}tr;
char st[MAXN];
int main(){
    for(int i=0;i<26;++i)
        ascii['a'+i]=i;
    int n;
    scanf("%d",&n);
    tr.init();
    while(n--){
        scanf("%s",st);
        tr.insertnode(st);
    }
    tr.build();
    scanf("%s",st);
    if(tr.query(st))
        printf("YES\n");
    else
        printf("NO\n");
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值