模板 ac自动机

 

题目描述

给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过。

输入输出格式

输入格式:

第一行一个n,表示模式串个数;

下面n行每行一个模式串;

下面一行一个文本串。

输出格式:

一个数表示答案

 

#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define inf 0x3f3f3f3f
#define lson l,m,pos<<1
#define rson m+1,r,pos<<1|1
const int N=1000000+5;
int tree[N][26],sum[N],fail[N],pos;
queue<int>q;
int ins(char *s)
{
    int len=strlen(s);int now=0;
    rep(i,0,len-1)
    {
        int ch=s[i]-'a';
        if(!tree[now][ch])tree[now][ch]=++pos;
        now=tree[now][ch];
    }
    sum[now]++;
}
void build()
{
    rep(i,0,25)
    if(tree[0][i])
    fail[tree[0][i]]=0,q.push(tree[0][i]);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        rep(i,0,25)
        if(tree[u][i])fail[tree[u][i]]=tree[fail[u]][i],q.push(tree[u][i]);
        else tree[u][i]=tree[fail[u]][i];
    }
}
int query(char *s)
{
    int len=strlen(s);int now=0,ans=0;
    rep(i,0,len-1)
    {
        now=tree[now][s[i]-'a'];
        for(int j=now;j&&sum[j]!=-1;j=fail[j])ans+=sum[j],sum[j]=-1;
    }
    return ans;
}

int n;
char p[N];
int main()
{
    RI(n);
    rep(i,1,n)
    {RS(p);ins(p);}

    build();
    RS(p);
    int ans=query(p);
    cout<<ans;
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/bxd123/p/10894503.html