题目背景

这是一道简单的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. java操作Excel的poi的字体设置

    package com.java.poi; import org.apache.poi.hssf.usermodel.HSSFWorkbook;import org.apache.poi.ss.use ...

  2. Mysql 设置起始值

    alter table t_tszj_pet_activity AUTO_INCREMENT=10000;   设置 id 从10000 开始

  3. 【转载】jmeter将上一个接口返回值作为下一个接口的请求参数

    第一:通过JSON Extractor 插件来提取JSON响应结果 原文地址:http://blog.csdn.net/dreamtl/article/details/68957122 接口响应结果, ...

  4. py西游公关之模块

    Py西游攻关之模块   模块&包(* * * * *) 模块(modue)的概念: 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可 ...

  5. 如何查看系统的界面,比如费用申请单的序时簿界面引用的是哪一个ListUi.快捷键alt+shift+d 然后选中该ListUI大框框,就可以看到引用的是哪一个了.

    如何查看系统的界面,比如费用申请单的序时簿界面引用的是哪一个ListUi.快捷键alt+shift+d 然后选中该ListUI大框框,就可以看到引用的是哪一个了.

  6. phpMyAdmin使用教程

    ---恢复内容开始--- wamp中自带了管理MySQL的phpMyAdmin,可用来本机测试,服务器维护,虚拟主机用户管理MySQL. 登录需记住servername,username,passwo ...

  7. PL\SQL(day05)

    PLSQL 1.常用的访问数据库的相关技术 1) plsql 过程化的sql 2) proc/c++ 在c/c++语言中访问oracle数据库的技术 3) ado/odbc vc中访问数据库的技术 4 ...

  8. 洛谷P1307 数字反转【水题】

    给定一个整数,请将该数各个位上数字反转得到一个新数.新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零(参见样例2). 输入输出格式 输入格式: 一个整数 NN ...

  9. Q&A to prepare interview of HSBC

    1.How do you keep updating lastest IT knowledge? 1).keep an eye on current project technology evetho ...

  10. Python SQLAlchemy ORM示例

    SQLAlchemy的是Python的SQL工具包和对象关系映射,给应用程序开发者提供SQL的强大功能和灵活性. 安装 pip install mysql-python pip install sql ...