洛谷.3808/3796.[模板]AC自动机
简单版:
#include <cstdio>
#include <cstring>
const int N=1e6+5,S=26;
char s[N];
struct AC_Automaton
{
int cnt,q[N],val[N],fail[N],las[N],son[N][S];
// struct Node
// {
// int val,las,fail,son[S];
// Node *son[S];//指针太麻烦了。。
// Node() {val=las=0, memset(son,0,sizeof son);}
// }pool[N];
void Insert(char *s)
{
int l=strlen(s),u=0;
for(int v,i=0; i<l; ++i)
{
v=s[i]-'a';
if(!son[u][v]) son[u][v]=++cnt;
u=son[u][v];
}
++val[u];
}
void Build()
{
int h=0,t=0;
for(int i=0; i<S; ++i)
if(son[0][i]) fail[son[0][i]]=0,q[t++]=son[0][i];
while(h<t)
{
int x=q[h++];
for(int v,i=0; i<S; ++i)
if(son[x][i])
fail[v=son[x][i]]=son[fail[x]][i], q[t++]=v, las[v]=val[fail[v]]?fail[v]:las[fail[v]];
else son[x][i]=son[fail[x]][i];
}
}
int Query(char *s)
{
int l=strlen(s),res=0,u=0;
for(int i=0; i<l; ++i)
{
u=son[u][s[i]-'a'];
for(int p=u; p&&~val[p]; p=las[p])
res+=val[p], val[p]=-1;
}
return res;
}
}ac;
int main()
{
int n; scanf("%d",&n);
while(n--) scanf("%s",s), ac.Insert(s);
ac.Build();
scanf("%s",s), printf("%d",ac.Query(s));
return 0;
}
增强版:1920ms(1268ms) 我说怎么慢。。数组开太大了
#include <cstdio>
#include <cstring>
#include <algorithm>
const int N=10505,S=26;
int n;
char s[155][75],p[1000005];
struct AC_Automaton
{
int cnt,q[N],val[N],fail[N],las[N],son[N][S],tm[155];
void Init()
{
cnt=0, memset(son,0,sizeof son), memset(val,0,sizeof val);
}
void Insert(char *s,int id)
{
int l=strlen(s),u=0;
for(int v,i=0; i<l; ++i)
{
v=s[i]-'a';
if(!son[u][v]) son[u][v]=++cnt;
u=son[u][v];
}
val[u]=id;
}
void Build()
{
int h=0,t=0;
for(int i=0; i<S; ++i)
if(son[0][i]) fail[son[0][i]]=0,q[t++]=son[0][i];
while(h<t)
{
int x=q[h++];
for(int v,i=0; i<S; ++i)
if(son[x][i])
fail[v=son[x][i]]=son[fail[x]][i], q[t++]=v, las[v]=val[fail[v]]?fail[v]:las[fail[v]];
else son[x][i]=son[fail[x]][i];
}
}
void Query(char *p)
{
memset(tm,0,sizeof tm);
int l=strlen(p),u=0,res=0;
for(int i=0; i<l; ++i)
{
u=son[u][p[i]-'a'];
for(int p=u; p; p=las[p])
++tm[val[p]];
}
for(int i=1; i<=n; ++i) res=std::max(res,tm[i]);
printf("%d\n",res);
for(int i=1; i<=n; ++i)
if(tm[i]==res) printf("%s\n",s[i]);
}
}ac;
int main()
{
while(scanf("%d",&n),n)
{
ac.Init();
for(int i=1; i<=n; ++i) scanf("%s",s[i]), ac.Insert(s[i],i);
ac.Build();
scanf("%s",p), ac.Query(p);
}
return 0;
}
增强版 第二次写(2018.4.5):1700ms(1204ms)
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
const int N=152*72,S=26;
int n;
char s[152][72],p[1000005];
struct AC_Automaton
{
int tot,son[N][27],fail[N],val[N],las[N],q[N],tm[152];
void Init(){
tot=0, memset(son,0,sizeof son), memset(val,0,sizeof val);
}
void Insert(char *s,int pos)
{
int l=strlen(s),x=0;
for(int id,i=0; i<l; ++i)
{
id=s[i]-'a';
if(!son[x][id]) son[x][id]=++tot;
x=son[x][id];
}
val[x]=pos;
}
void Build()
{
int h=0,t=0;
for(int i=0; i<S; ++i)
if(son[0][i]) fail[son[0][i]]=0,q[t++]=son[0][i];
while(h<t)
{
int x=q[h++];
for(int v,i=0; i<S; ++i)
if(son[x][i])
fail[v=son[x][i]]=son[fail[x]][i],q[t++]=v,las[v]=val[fail[v]]?fail[v]:las[fail[v]];
else son[x][i]=son[fail[x]][i];
}
}
void Query(char *p)
{
int l=strlen(p),res=0,x=0;
memset(tm,0,sizeof tm);
for(int i=0; i<l; ++i)
{
x=son[x][p[i]-'a'];
for(int j=x; j; j=las[j]) ++tm[val[j]];
}
for(int i=1; i<=n; ++i) if(res<tm[i]) res=tm[i];
printf("%d\n",res);
for(int i=1; i<=n; ++i) if(tm[i]==res) printf("%s\n",s[i]);
}
}ac;
int main()
{
while(scanf("%d",&n),n){
ac.Init();
for(int i=1; i<=n; ++i) scanf("%s",s[i]),ac.Insert(s[i],i);
ac.Build(), scanf("%s",p), ac.Query(p);
}
return 0;
}
洛谷.3808/3796.[模板]AC自动机的更多相关文章
- [洛谷3808]【模板】AC自动机(简单版)
题目大意: 给定$n$个模式串$p(\sum|p_i|\le10^6)$和一个$t(|t|\le10^6)$,求在$t$中被匹配的$p$的个数. 思路: AC自动机模板题,注意$t$中一个字符可能对应 ...
- 洛谷P3966 [TJOI2013]单词(AC自动机)
题目描述 小张最近在忙毕设,所以一直在读论文.一篇论文是由许多单词组成但小张发现一个单词会在论文中出现很多次,他想知道每个单词分别在论文中出现了多少次. 输入输出格式 输入格式: 第一行一个整数N,表 ...
- 洛谷P3966 单词 [TJOI2013] AC自动机
正解:AC自动机 解题报告: 传送门! 先来提供一个40pts错解QAQ 首先看到这题就会想到AC自动机板子题2鸭!然后就照着那题的套路打一下,随便改一点儿,简单来说就是每次经过一个节点都要++,然后 ...
- 洛谷P2444 病毒 [POI2000] AC自动机
正解:AC自动机 解题报告: 传送门! 首先看到这种题目二话不说先把trie树和fail指针建立起来 然后就想鸭,如果我们想让模式串和文本串尽量不能匹配,就要想办法让它跳fail指针,而不是继续往下走 ...
- 洛谷P2444 病毒【AC自动机】
题目描述 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会已经找出了所有的病毒代码段,试问,是否 ...
- 洛谷2414(构建ac自动机fail树dfs序后遍历Trie树维护bit及询问答案)
要点 这是一道蔡队题,看我标题行事 任意询问y串上有多少个x串,暴力找每个节点是不是结尾肯定是炸的,考虑本质:如果某节点是x的结尾,根据ac自动机的性质,x一定是此(子)串后缀.又有每个Trie节点的 ...
- 洛谷 P3370 【模板】字符串哈希
洛谷 P3370 [模板]字符串哈希 题目描述 如题,给定N个字符串(第i个字符串长度为Mi,字符串内包含数字.大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串. 友情提醒:如果真的 ...
- 洛谷P3369 【模板】普通平衡树(Treap/SBT)
洛谷P3369 [模板]普通平衡树(Treap/SBT) 平衡树,一种其妙的数据结构 题目传送门 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除 ...
- 最小生成树 & 洛谷P3366【模板】最小生成树 & 洛谷P2820 局域网
嗯... 理解生成树的概念: 在一幅图中将所有n个点连接起来的n-1条边所形成的树. 最小生成树: 边权之和最小的生成树. 最小瓶颈生成树: 对于带权图,最大权值最小的生成树. 如何操作? 1.Pri ...
随机推荐
- linux安装MongoDB
安装 32bit的mongodb最大只能存放2G的数据,64bit就没有限制 到官网,选择合适的版本下载,本次下载3.4.0版本 解压 tar -zxvf mongodb-linux-x86_64-u ...
- js 图片转换base64 base64转换为file对象
function getImgToBase64(url,callback){//将图片转换为Base64 var canvas = document.createElement('canvas'), ...
- The.Glory.of.Innovation 创新之路3放飞好奇
教育最重要的就是 问题不在于教他各种学问,而在于培养他爱好学问的兴趣,而且在这种兴趣充分增长起来的时候,教他以研究学问的方法. ———— 卢梭 如何辨识不同的观点, 老师考查的重点不在于学生 ...
- 爬取文件时,对已经操作过的URL进行过滤
爬取文件时,对已经操作过的URL进行过滤 1.创建过滤规则文件filter.py在spiders同级目录 class RepeatUrl: def __init__(self): self.visit ...
- Php7有哪些新特性:
PHP7在PHP5的基础上又做了一次质的提升,当然改变很多,我这里以我的总结简单说下,主要发生了下面这些更改: 移除了一些旧的特性 ZEND引擎升级到Zend Engine 3,也就是所谓的PHP N ...
- 解决Windows Server 2008R2通过计划任务定时执行bat文件,显示成功但实际未执行
前段时间在Windows Server 2008安装了一套基于MySQL数据库的软件,处于数据安全的考虑,希望每天能够自动进行数据库备份.我在别人脚本的基础上自己写了一个数据库备份的bat脚本,双击该 ...
- mysql基本操作(一)
1.登录mysql mysql -h localhost -u root -p 登录mysql,其中 -h是指定要连接mysql服务器的主机名 -u是指定用户 -次数登录必须用-p输入密 ...
- MyEclipse 8.6 下载
Downloads: MyEclipse 8.6 for Eclipse Galileo Windows http://downloads.myeclipseide.com/downloads/pro ...
- Coolpy网络部署说明(局域网)
本文将介绍Coolpy第一种方案的网络部署方法.以方便大家学习如何让coolpy设备部署到相应的应用场景中.本例将以水星MW310R无线路由器作为演示路由器. 1.局域网部署 即coolpy设备=&g ...
- postgresql 查询某一个表中的所有字段
select * from information_schema.columns where table_schema='public' and table_name='表名称 ';