题目背景
这是一道简单的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;
}