题目背景

这是一道简单的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;

也是模板,没什么么好说的,

只不过每次更新的时候是++,而不是=1!

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#include<map>
using namespace std;
const int MAXN=;
void read(int &n)
{
char c='+';int x=;bool flag=;
while(c<''||c>''){c=getchar();if(c=='-')flag=;}
while(c>=''&&c<=''){x=x*+c-;c=getchar();}
flag==?n=-x:n=x;
}
char s[MAXN];
char text[MAXN];
int n;
int ans=;
struct AC_Automata
{
int sz;
int ch[MAXN][];//trie树
int val[MAXN];// 记录是否有单词
int last[MAXN];
int f[MAXN];
int sigma_sz;
void Init()
{
memset(ch[],,sizeof(ch[]));
sz=;
sigma_sz=;
}
int idx(char c)
{
return c-'a';
}
void Insert(char *s,int pos)
{
int l=strlen(s); int now=;
for(int i=;i<l;i++)
{
int c=idx(s[i]);
if(!ch[now][c])
{
memset(ch[sz],,sizeof(ch[sz]));
val[sz]=;
ch[now][c]=sz++;
}
now=ch[now][c];
}
val[now]++;//一个单词的结束
}
void getfail()
{
f[]=;
queue<int>q;
for(int i=;i<sigma_sz;i++)
{
int u=ch[][i];
if(u)// 此处有单词出现
{
f[u]=;// 连向根节点
q.push(u);
last[u]=;// 上一个出现的单词一定是根节点
// 上面两条语句没什么卵用,只是为了帮助理解AC自动机的含义
}
}
while(!q.empty())
{
int p=q.front();q.pop();
for(int i=;i<sigma_sz;i++)
{
int u=ch[p][i];
if(!u)//没有孩子
{
ch[p][i]=ch[f[p]][i];// 补上一条不存在的边,减少查找次数
continue;
}
q.push(u);
int v=f[p];// 找到它的失陪指针
f[u]=ch[v][i];//因为我们在上面补上了一条不存在边,所以他一定存在孩子
last[u]=val[f[u]] ? f[u] : last[f[u]];
//判断下是不是单词结尾 是, 不是
}
}
}
int ok(int pos)
{
if(val[pos])
{
ans+=val[pos];
val[pos]=;
ok(last[pos]);
}
}
void find(char *s)// 查找模式串
{
int l=strlen(s);
int j=;// 当前节点的编号
for(int i=;i<l;i++)
{
int c=idx(s[i]);
while(j&&!ch[j][c])
j=f[j];// 顺着失配边走
j=ch[j][c]; // 取到儿子
if(val[j])
ok(j);// 找到一个单词
else if(last[j])
ok(last[j]);// 当前节点不行就看看上一个单词出现的位置行不行
}
}
}ac;
int main()
{
scanf("%d",&n);
ac.Init();
for(int i=;i<=n;i++)
{
scanf("%s",s);
ac.Insert(s,i);
}
ac.getfail();
scanf("%s",text);
ac.find(text);
printf("%d\n",ans);
return ;
}

P3808 【模版】AC自动机(简单版)的更多相关文章

  1. [模板][P3808]AC自动机(简单版)

    Description: 求n个模式串中有几个在文本串中出现 Solution: 模板,详见代码: #include<bits/stdc++.h> using namespace std; ...

  2. [算法模版]AC自动机

    [算法模版]AC自动机 基础内容 板子不再赘述,OI-WIKI有详细讲解. \(query\)函数则是遍历文本串的所有位置,在文本串的每个位置都沿着\(fail\)跳到根,将沿途所有元素答案++.意义 ...

  3. 洛谷P3808 & P3796 AC自动机模板

    题目:P3808:https://www.luogu.org/problemnew/show/P3808 P3796:https://www.luogu.org/problemnew/show/P37 ...

  4. Ring HDU - 2296 AC自动机+简单DP和恶心的方案输出

    题意: 就是现在给出m个串,每个串都有一个权值,现在你要找到一个长度不超过n的字符串, 其中之前的m个串每出现一次就算一次那个字符串的权值, 求能找到的最大权值的字符串,如果存在多个解,输出最短的字典 ...

  5. POJ 1625 Censored!(AC自动机->指针版+DP+大数)题解

    题目:给你n个字母,p个模式串,要你写一个长度为m的串,要求这个串不能包含模式串,问你这样的串最多能写几个 思路:dp+AC自动机应该能看出来,万万没想到这题还要加大数...orz 状态转移方程dp[ ...

  6. 小明系列故事――女友的考验 HDU - 4511 AC自动机+简单DP

    题意:自己看题目,中文体面. 题解: 把所有不能走的路径放入AC自动机中. 然后DP[i][j]表示走到 i 这个点,且位于AC自动机 j 这个节点最短距离 然后直接DP即可.注意一点会爆int #i ...

  7. Walk Through Squares HDU - 4758 AC自动机+简单状压DP

    题意:给你两个串,求用m个R,n个D能组成多少个包含这两个串 题解:先构造一个AC自动机记录每个状态包含两个串的状态, 状态很容易定义 dp[i][j][k][status]表示在AC自动机K这个节点 ...

  8. Censored! - POJ 1625(ac自动机+简单dp+高精度运算)

    题目大意:首先给一个字符集合,这个集合有N个字符,然后需要一个长度为M的句子,但是据子里面不能包含的串有P个,每个串里面的字符都是有字符集和里面的字符构成的,现在想知道最多能构造多少个不重复的句子. ...

  9. AC自动机例题

    P3808 [模板]AC自动机(简单版) [题目描述] 给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过. #include<bits/stdc++.h> using name ...

  10. 【AC自动机】AC自动机

    Definition & Solution AC自动机是一种多模式串的字符串匹配数据结构,核心在于利用 fail 指针在失配时将节点跳转到当前节点代表字符串的最长后缀子串. 首先对 模式串 建 ...

随机推荐

  1. js 验证文件格式和大小

    <script> $('#btnSearch').click(function(){ // alert("000");// fileElem = document.ge ...

  2. 微信小程序,时间戳和日期格式互相转化

    微信小程序,时间戳转为日期格式 通常后台传递过来的都是时间戳,但是前台展示不能展示时间戳.就需要转化了. 功能说明: 微信小程序里,时间戳转化为日期格式,支持自定义. 拷贝至项目utils/utils ...

  3. 利用node、express初始化项目

    前端做整站是开发,例如:前端是用了vue创建初始化项目,后端我们不会php.java等,我们只能用node去创建去做后端代码,本文就给大家讲解最基础的从零开始创建一个项目的后端环境. 一般来说前后端代 ...

  4. 【CF1173D】NanuuAndCircle

    题目链接:http://codeforces.com/contest/1173/problem/D 赛场上弱爆了的小菜鸡(本人),怎么也没想到这道看起来近似于神仙计数/生成函数的题正解竟然如此简洁. ...

  5. 第2章 this 、 call 和 apply

    第一部分 基础知识 第2章  this . call 和 apply 2.1  this JavaScript的 this 总是指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的, ...

  6. [jzoj5786]【NOIP2008模拟】观察 (dfs序+lca)

    传送门 Description infleaking十分愉快地走在路上, 因为经过10^9^9^9年后, 他得到了一个新技能--观察大法. 刚出来的infleaking就想要挑战自我. 为什么infl ...

  7. php实现网站访客数量统计的方法(简单实现,不能防刷新)

    方法一: <?php function Counter()//定义函数 { $five = "00000";//声明变量,$five,$four等变量表示零的个数,放在数字前 ...

  8. mysql优化sql语句

    mysql优化sql语句   常见误区   www.2cto.com   误区1:   count(1)和count(primary_key) 优于 count(*)   很多人为了统计记录条数,就使 ...

  9. poj 1523 求割点把一个图分成几个联通部分

    #include<stdio.h> #include<string.h> #define N 1100 struct node { int u,v,next; }bian[N* ...

  10. hdu 1250 简单大整数加法

    #include<stdio.h> #include<string.h> #define N 3100 int a[N],b[N],c[N],d[N],e[N]; int ma ...