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 ...
随机推荐
- OpenCV.20190628
1.OpenCV提取ORB特征并匹配 - 简书.html(https://www.jianshu.com/p/420f8211d1cb) OpenCV提取ORB特征并匹配 - 简书.html(http ...
- SQL SERVER ISDATE函数
定义: ISDATE函数判断指定字符串是否是有效日期. 语法: ISDATE(date) 参数: ①date是需要判定是否是有效日期的字符串 返回值: int型数据 例: 声明:本文是本人查阅网上及 ...
- shiro小记
今天主要看了Shiro的认证,授权功能初步了解了一下,其他的功能用的不多,之后再看. 先说一下Shiro的三个核心概念: 1.Subject: 代表当前正在执行操作的用户,但Subject代表的可以是 ...
- (一)springMvc 底层运作流程
目录 什么是 springMvc SpringMVC的底层运作流程 什么是 springMvc springMvc 是spring 框架的一个模块,这也就意味着二者不需要通过整合层(整合包)进行整合 ...
- docker-registry的定制和性能分析
docker-index Web UI Meta-data 元数据存储(附注.星级.公共库清单) 访问认证 token管理 存储镜像.以及镜像层的家族谱系 没有用户账户数据 不知道用户的账户和安全性 ...
- Payload 实现分离免杀
众所周知,目前的杀毒软件的杀毒原理主要有三种方式,一种基于特征,一种基于行为,一种基于云查杀,其中云查杀的一些特点基本上也可以概括为特征码查杀,不管是哪一种杀毒软件,都会检查PE文件头,尤其是当后门程 ...
- 轻松入门CAS系列(1)-轻松看懂企业单点登录的解决方案
常见的企业应用情况 企业内部的信息化一般都是一个过程中的 ,起初企业为了部分管理的需要,会上线几个信息化系统:后来对这块慢慢重视,信息系统会越来越多.开始,只有一两个系统时,员工还好,靠脑袋还能记得住 ...
- Docker Registry搭建
一.前言 Docker官方镜像仓库 访问速度很慢,Docker Registry允许搭建我们自己的镜像仓库,为实现镜像拉取.推送提供便利. 二.安装与启动 1.创建目录 mkdir /usr/loca ...
- SparkSQL读取HBase数据
这里的SparkSQL是指整合了Hive的spark-sql cli(关于SparkSQL和Hive的整合,见文章后面的参考阅读). 本质上就是通过Hive访问HBase表,具体就是通过hive-hb ...
- VisualStudio2015 安装
环境:Win10 64位 推荐安装顺序 IIS > Sqlserver > Asp.Net 启动安装程序(出现Logo后需要等待1到2分钟),选择安装路径(注意不要出现中文路径) 勾选需求 ...