【洛谷P3808】【模版】AC自动机(简单版)

来源:互联网 发布:禁止在淘宝网上出售 编辑:程序博客网 时间:2024/05/20 15:37

题目背景

这是一道简单的AC自动机模版题。

用于检测正确性以及算法常数。

为了防止卡OJ,在保证正确的基础上只有两组数据,请不要恶意提交。

题目描述

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

输入输出格式

输入格式:
第一行一个n,表示模式串个数;

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

下面一行一个文本串。

输出格式:
一个数表示答案

输入输出样例

输入样例#1:
2
a
aa
aa
输出样例#1:
2
说明

subtask1[50pts]:∑length(模式串)<=10^6,length(文本串)<=10^6,n=1;

subtask2[50pts]:∑length(模式串)<=10^6,length(文本串)<=10^6;

题解
AC自动机裸题

代码(trie图版)

#include<cstdio>#include<cstring>#include<iostream>using namespace std;inline int read(){    int x=0,f=1;char ch=getchar();    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}char s[1000001];int T,n,tot,ans;int a[1000001][26],q[1000001],point[1000001],danger[1000001];inline void ins(){    int now=1,l=strlen(s);    for (int i=0;i<l;i++)    {        int t=s[i]-'a';        if (!a[now][t]) a[now][t]=++tot;        now=a[now][t];    }    danger[now]++;}inline void acmach(){    int Head=0,tail=1;    q[1]=1;point[1]=0;    while (Head!=tail)    {        int now=q[++Head];        for (int i=0;i<26;i++)        {            if (a[now][i])            {                point[a[now][i]]=a[point[now]][i];                q[++tail]=a[now][i];            }            else a[now][i]=a[point[now]][i];        }    }}inline void solve(){    int now=1,l=strlen(s);    for (int i=0;i<l;i++)    {        int t=s[i]-'a';        now=a[now][t];        for (int j=now;j&&danger[j]!=-1;j=point[j])            ans+=danger[j],danger[j]=-1;    }    printf("%d",ans);}int main(){    for (int i=0;i<26;i++) a[0][i]=1;    n=read();tot=1;    while (n--)    {        scanf("%s",s);        ins();    }    acmach();    scanf("%s",s);    solve();    return 0;}