题目背景
这是一道简单的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自动机的模板题,正好整理一下模板,看了看wsj的代码并且结合最近几天所听到的一些知识,整理了整理也就大了一下,然后就过了,发现并没有多大难度,
只要理会就好了,之后我会再写一篇关于AC自动机的Blog,现在先水水几道水题,模板题先过了,再说。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #include<queue> 7 using namespace std; 8 9 int n,cnt=1; 10 char s[1000007]; 11 struct Node 12 { 13 int c[26],suf,flag; 14 }tree[1000007]; 15 16 inline void Ins() 17 { 18 int head=1,l=strlen(s); 19 for (int i=0;i<l;i++) 20 { 21 int now=s[i]-‘a‘; 22 if (!tree[head].c[now]) tree[head].c[now]=++cnt; 23 head=tree[head].c[now]; 24 } 25 tree[head].flag++; 26 } 27 void Make_AC() 28 { 29 for (int i=0;i<26;i++) tree[0].c[i]=1; 30 int head=0,tail=1; 31 queue<int>q; 32 while (!q.empty()) q.pop(); 33 tree[1].suf=0; 34 q.push(1); 35 while (!q.empty()) 36 { 37 int u=q.front(); 38 q.pop(); 39 for (int i=0;i<26;i++) 40 if (tree[u].c[i]) 41 { 42 tree[tree[u].c[i]].suf=tree[tree[u].suf].c[i]; 43 q.push(tree[u].c[i]); 44 } 45 else tree[u].c[i]=tree[tree[u].suf].c[i]; 46 } 47 } 48 void Solve() 49 { 50 scanf("%s",s); 51 int ans=0,head=1,len=strlen(s); 52 for (int i=0;i<len;i++) 53 { 54 int now=s[i]-‘a‘; 55 head=tree[head].c[now]; 56 for (int j=head;j&&tree[j].flag!=-1;j=tree[j].suf) 57 ans+=tree[j].flag,tree[j].flag=-1; 58 } 59 printf("%d\n",ans); 60 } 61 int main() 62 { 63 scanf("%d",&n); 64 while (n--){scanf("%s",s);Ins();} 65 Make_AC(); 66 Solve(); 67 }
时间: 2024-11-03 22:20:38