luogu 3808 【模板】AC自动机(简单版)
题目背景
这是一道简单的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自动机 然后将文本串在ACM上跑 统计答案的时候暴力跳fail表示求我这个点的后缀有多少是答案 但是因为fail树很多最后会汇流到一起而我们统计的是有几个出现所以统计之后要改成0
#include#include#includeusing namespace std;const int N=1e6+10;char s[N];int cnt=1,n,sum[N],fail[N],trans[N][26];inline void insert1(char *s){ static int p;p=1; for (int i=1,nxt;s[i];++i){ if (!trans[p][s[i]-'a']) trans[p][s[i]-'a']=nxt=++cnt; else nxt=trans[p][s[i]-'a'];p=nxt; }++sum[p];}inline void buildAC(){ queueq;q.push(1);for (int i=0;i<26;++i) trans[0][i]=1; while(!q.empty()){ int x=q.front();q.pop(); for (int i=0;i<26;++i){ int &y=trans[x][i]; if (!y) {y=trans[fail[x]][i];continue;} fail[y]=trans[fail[x]][i];q.push(y); } }}int main(){ freopen("luogu3808.in","r",stdin); scanf("%d",&n);int ans=0; for (int i=1;i<=n;++i) scanf("%s",s+1),insert1(s); scanf("%s",s+1);int p=1;buildAC(); for (int i=1;s[i];++i){ p=trans[p][s[i]-'a']; for (int j=p;j&&sum[j];j=fail[j]) ans+=sum[j],sum[j]=0; }printf("%d\n",ans); return 0;}
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
暂时没有评论,来抢沙发吧~