P5357 【模板】AC自动机(二次加强版)
思路
这题可以同时作为AC自动机和SAM的模板啊喂
AC自动机
对T建出AC自动机,把S在上面匹配,然后记录每个点被经过的次数,最后统计一次即可(暴力跳fail的复杂度是不对的)
SAM
对S建出SAM,然后每次把T在上面匹配,如果匹配长度等于T的长度,输出出现次数,否则输出0
但是卡了SAM的空间
代码
AC自动机
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int trans[200200][26],fail[200200],ends[200200],cnt[200200],Nodecnt=0,root=0,n;
char s[2000200];
void insert(char *s,int len,int inq){
int p=root;
for(int i=0;i<len;i++){
if(!trans[p][s[i]-'a'])
trans[p][s[i]-'a']=++Nodecnt;
p=trans[p][s[i]-'a'];
}
ends[inq]=p;
}
queue<int> q;
void get_AC(void){
for(int i=0;i<26;i++)
if(trans[root][i]){
fail[trans[root][i]]=root;
q.push(trans[root][i]);
}
while(!q.empty()){
int x=q.front();
q.pop();
for(int i=0;i<26;i++){
if(trans[x][i]){
fail[trans[x][i]]=trans[fail[x]][i];
q.push(trans[x][i]);
}
else
trans[x][i]=trans[fail[x]][i];
}
}
}
int in[2000200];
void topu(void){
for(int i=1;i<=Nodecnt;i++)
in[fail[i]]++;
for(int i=1;i<=Nodecnt;i++)
if(!in[i])
q.push(i);
while(!q.empty()){
int x=q.front();
q.pop();
cnt[fail[x]]+=cnt[x];
in[fail[x]]--;
if(!in[fail[x]])
q.push(fail[x]);
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",s);
insert(s,strlen(s),i);
}
get_AC();
scanf("%s",s);
int lent=strlen(s),p=root;
for(int i=0;i<lent;i++){
p=trans[p][s[i]-'a'];
cnt[p]++;
}
topu();
for(int i=1;i<=n;i++){
printf("%d\n",cnt[ends[i]]);
}
return 0;
}
SAM
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <iostream>
#include <queue>
using namespace std;
int maxlen[1001000*2],trans[1001000*2][26],suflink[1001000*2],n,Nodecnt=1,len,endpos[1001000*2];
char S[1001000];
string T[200100];
int New_state(int _maxlen,int *_trans,int _suflink){
++Nodecnt;
maxlen[Nodecnt]=_maxlen;
if(_trans)
for(int i=0;i<26;i++)
trans[Nodecnt][i]=_trans[i];
suflink[Nodecnt]=_suflink;
return Nodecnt;
}
int add_len(int u,int c){
int z=New_state(maxlen[u]+1,NULL,0);
endpos[z]=1;
while(u&&trans[u][c]==0){
trans[u][c]=z;
u=suflink[u];
}
if(!u){
suflink[z]=1;
return z;
}
int v=trans[u][c];
if(maxlen[v]==maxlen[u]+1){
suflink[z]=v;
return z;
}
int y=New_state(maxlen[u]+1,trans[v],suflink[v]);
suflink[z]=suflink[v]=y;
while(u&&trans[u][c]==v){
trans[u][c]=y;
u=suflink[u];
}
return z;
}
int ranks[1001000*2],barrel[1001000*2];
void c_sort(int n,int lim){
memset(barrel,0,sizeof(barrel));
for(int i=1;i<=Nodecnt;i++)
barrel[maxlen[i]]++;
for(int i=1;i<=lim;i++)
barrel[i]+=barrel[i-1];
for(int i=1;i<=Nodecnt;i++)
ranks[barrel[maxlen[i]]--]=i;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
cin>>T[i];
scanf("%s",S+1);
len=strlen(S+1);
int last=1;
for(int i=1;i<=len;i++)
last=add_len(last,S[i]-'a');
c_sort(Nodecnt,len);
for(int i=Nodecnt;i>=1;i--)
endpos[suflink[ranks[i]]]+=endpos[ranks[i]];
for(int i=1;i<=n;i++){
int lent=T[i].length();
int nowp=1,matchlen=0;
for(int j=0;j<lent;j++){
if(trans[nowp][T[i][j]-'a']){
matchlen++;
nowp=trans[nowp][T[i][j]-'a'];
}
else{
while(nowp&&trans[nowp][T[i][j]-'a']==0)
nowp=suflink[nowp];
if(!nowp){
nowp=1;
matchlen=0;
}
else{
matchlen=maxlen[nowp]+1;
nowp=trans[nowp][T[i][j]-'a'];
}
}
}
if(matchlen==lent){
// int ans=0;
// while(nowp){
// ans+=endpos[nowp];
// nowp=suflink[nowp];
// }
printf("%d\n",endpos[nowp]);
}
else{
printf("0\n");
}
}
return 0;
}
P5357 【模板】AC自动机(二次加强版)的更多相关文章
- luoguP3796[模板]AC自动机(加强版)
传送门 ac自动机模板,可能我写的ac自动机是有点问题的,所以跑的有些慢 暴力跳fail统计 代码: #include<cstdio> #include<iostream> # ...
- 【模版 Luogu P3808/P3796/P5357】AC自动机(简论)
浙江集训Day9,没有出任何实质性成果,只好把昨天打完的板子记一下. 该博客基于luogu的三道模版题.只有一个大致的讲解,主要提供代码给自己参考. ------------------------- ...
- luoguP3808[模板]AC自动机(简单版)
传送门 ac自动机模板题,裸的多串匹配 代码: #include<cstdio> #include<iostream> #include<algorithm> #i ...
- UVA 11019 Matrix Matcher ( 二维字符串匹配, AC自动机 || 二维Hash )
题目: 传送门 题意: 给你一个 n * m 的文本串 T, 再给你一个 r * c 的模式串 S: 问模式串 S 在文本串 T 中出现了多少次. 解: 法一: AC自动机 (正解) 670ms 把模 ...
- 算法模板——AC自动机
实现功能——输入N,M,提供一个共计N个单词的词典,然后在最后输入的M个字符串中进行多串匹配(关于AC自动机算法,此处不再赘述,详见:Aho-Corasick 多模式匹配算法.AC自动机详解.考虑到有 ...
- 模板 AC自动机
题目描述 有$N$ 个由小写字母组成的模式串以及一个文本串$T$ .每个模式串可能会在文本串中出现多次.你需要找出哪些模式串在文本串$T$ 中出现的次数最多. 输入输出格式 输入格式: 输入含多组数据 ...
- pku1204 Word Puzzles AC自动机 二维字符串矩阵8个方向找模式串的起点坐标以及方向 挺好的!
/** 题目:pku1204 Word Puzzles 链接:http://poj.org/problem?id=1204 题意:给定一个L C(C <= 1000, L <= 1000) ...
- 算法竞赛模板 AC自动机
AC自动机基本操作 (1) 在AC自动机中,我们首先将每一个模式串插入到Trie树中去,建立一棵Trie树,然后构建fail指针. (2) fail指针,是穿插在Trie树中各个结点之间的指针,顾名思 ...
- UVa 11019 (AC自动机 二维模式串匹配) Matrix Matcher
就向书上说得那样,如果模式串P的第i行出现在文本串T的第r行第c列,则cnt[r-i][c]++; 还有个很棘手的问题就是模式串中可能会有相同的串,所以用repr[i]来记录第i个模式串P[i]第一次 ...
- AC自动机(二维) UVA 11019 Matrix Matcher
题目传送门 题意:训练指南P218 分析:一行一行的插入,一行一行的匹配,当匹配成功时将对应子矩阵的左上角位置cnt[r][c]++;然后统计 cnt[r][c] == x 的数量 #include ...
随机推荐
- java中类加载的全过程及内存图分析
类加载机制: jvm把class文件加载到内存,并对数据进行校验.解析和初始化,最终形成jvm可以直接使用的java类型的过程. (1)加载 将class文件字节码内容加载到内存中,并将这些静态数据转 ...
- HIVE配置mysql metastore
HIVE配置mysql metastore hive中除了保存真正的数据以外还要额外保存用来描述库.表.数据的数据,称为hive的元数据.这些元数据又存放在何处呢? 如果不修改配置hive ...
- java面试指导_垃圾收集
Java 的自动内存管理主要是针对对象内存的回收和对象内存的分配.同时,Java 自动内存管理最核心的功能是 堆 内存中对象的分配与回收. Java 堆是垃圾收集器管理的主要区域,因此也被称作GC 堆 ...
- Mybatis插件之Mybatis-Plus(SpringBoot)
这边只在SpringBoot下进行简单查询的测试,接下来会博客会介绍增删改的操作. 数据库表结构如下: 开始测试: 1.新建工程(trymp_springboot)并把项目结构建立好 2.导入pom. ...
- Hadoop之HDFS介绍
1. 概述 HDFS是一种分布式文件管理系统. HDFS的使用场景: 适合一次写入,多次读出的场景,且不支持文件的修改: 适合用来做数据分析,并不适合用来做网盘应用: 1.2 优缺点 优点: 高容错性 ...
- 【转帖】Samba AD DC(域控制器)的配置
Samba AD DC(域控制器)的配置 http://lihaitao.cn/?p=299 山东前辈写的blog 挺好的.. 改天做实验. 发表于2017年3月7日由李海涛 ■Samba AD DC ...
- 粒子群算法(PSO)
这几天看书的时候看到一个算法,叫粒子群算法,这个算法挺有意思的,下面说说我个人的理解: 粒子群算法(PSO)是一种进化算法,是一种求得近似最优解的算法,这种算法的时间复杂度可能会达到O(n!),得到的 ...
- NIO总结-----Buffer
Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的. 缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO ...
- MQTT协议探究(三)
1 回顾与本次目标 1.1 回顾 主题通配符 主题语义和用法 WireShark进行抓包分析了报文 报文分析: SUBSCRIBE--订阅主题 SUBACK--订阅确认 UNNSUBSCRIBE--取 ...
- JDK + Tomcat 安装 + 制作自定义镜像【第 2 篇 Tomcat】
[第 1 篇 JDK]:https://www.cnblogs.com/del88/p/11842387.html[第 2 篇 Tomcat]:https://www.cnblogs.com/del8 ...