AC自动机模板

#include <bits/stdc++.h>
#define ll long long
#define eps 1e-7
using namespace std;
inline int read(){
    int x=0;int f=1;char ch=getchar();
    while(ch>'9'||ch<'0') {if(ch=='-') f=-1;ch=getchar();}
    while(ch<='9'&&ch>='0') {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int MAXN=1e+10;
struct node {
    int endflag;
    int value;
    int linkk[26];
    int fail;
}tree[500010];
int root=0;
int slen;
char str[1000100];
int q[1000010];
int len,n;
void buildtrie(int x,int node){
    int s=str[x]-'a';
    if(!tree[node].linkk[s]){
        tree[node].linkk[s]=++len;
        tree[len].endflag=0;
        tree[len].fail=root;
    }
    int nextnode=tree[node].linkk[s];
    if(x==slen-1){
        tree[nextnode].endflag++;
        return ;
    }
    buildtrie(x+1,nextnode);
}
void init(){
    cin>>n;
    memset(tree,0,sizeof(tree));
    for(int i=1;i<=n;i++){
        scanf("%s",str);
        slen=strlen(str);
        buildtrie(0,root);
    }
}
void buildac(){
   int head=0;
   int tail=0;
   q[++tail]=root;
   while(head<tail){
        int now=q[++head];
        for(int i=0;i<26;i++){
            if(tree[now].linkk[i]){
	            int nextnode=tree[now].linkk[i];
	            if(now!=root){
                    int temp=tree[now].fail;
	                while(temp!=root&&!tree[temp].linkk[i]){
	                    temp=tree[temp].fail;
	                }
	                tree[nextnode].fail=tree[temp].linkk[i];
	            }
	            q[++tail]=nextnode;
	        }
        }
    }
}
void find(){
    int ans=0;
    scanf("%s",str);
    int len=strlen(str);
    int now=root;
    for(int i=0;i<len;i++){
        int chindex=str[i]-'a';
        while(!tree[now].linkk[chindex]&&now!=root){
            now=tree[now].fail;
        }
        now=tree[now].linkk[chindex];
        int temp=now;
        while(temp!=root&&tree[temp].endflag>-1){
            ans+=tree[temp].endflag;
            tree[temp].endflag=-1;
            temp=tree[temp].fail;
        }
    }
    cout<<ans<<endl;
}
int main(){
    init();
    buildac();
    find();
    return 0;
}

  

转载于:https://www.cnblogs.com/something-for-nothing/p/8861375.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值