题目链接:简单版增强版

简单版:

#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自动机的更多相关文章

  1. [洛谷3808]【模板】AC自动机(简单版)

    题目大意: 给定$n$个模式串$p(\sum|p_i|\le10^6)$和一个$t(|t|\le10^6)$,求在$t$中被匹配的$p$的个数. 思路: AC自动机模板题,注意$t$中一个字符可能对应 ...

  2. 洛谷P3966 [TJOI2013]单词(AC自动机)

    题目描述 小张最近在忙毕设,所以一直在读论文.一篇论文是由许多单词组成但小张发现一个单词会在论文中出现很多次,他想知道每个单词分别在论文中出现了多少次. 输入输出格式 输入格式: 第一行一个整数N,表 ...

  3. 洛谷P3966 单词 [TJOI2013] AC自动机

    正解:AC自动机 解题报告: 传送门! 先来提供一个40pts错解QAQ 首先看到这题就会想到AC自动机板子题2鸭!然后就照着那题的套路打一下,随便改一点儿,简单来说就是每次经过一个节点都要++,然后 ...

  4. 洛谷P2444 病毒 [POI2000] AC自动机

    正解:AC自动机 解题报告: 传送门! 首先看到这种题目二话不说先把trie树和fail指针建立起来 然后就想鸭,如果我们想让模式串和文本串尽量不能匹配,就要想办法让它跳fail指针,而不是继续往下走 ...

  5. 洛谷P2444 病毒【AC自动机】

    题目描述 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会已经找出了所有的病毒代码段,试问,是否 ...

  6. 洛谷2414(构建ac自动机fail树dfs序后遍历Trie树维护bit及询问答案)

    要点 这是一道蔡队题,看我标题行事 任意询问y串上有多少个x串,暴力找每个节点是不是结尾肯定是炸的,考虑本质:如果某节点是x的结尾,根据ac自动机的性质,x一定是此(子)串后缀.又有每个Trie节点的 ...

  7. 洛谷 P3370 【模板】字符串哈希

    洛谷 P3370 [模板]字符串哈希 题目描述 如题,给定N个字符串(第i个字符串长度为Mi,字符串内包含数字.大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串. 友情提醒:如果真的 ...

  8. 洛谷P3369 【模板】普通平衡树(Treap/SBT)

    洛谷P3369 [模板]普通平衡树(Treap/SBT) 平衡树,一种其妙的数据结构 题目传送门 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除 ...

  9. 最小生成树 & 洛谷P3366【模板】最小生成树 & 洛谷P2820 局域网

    嗯... 理解生成树的概念: 在一幅图中将所有n个点连接起来的n-1条边所形成的树. 最小生成树: 边权之和最小的生成树. 最小瓶颈生成树: 对于带权图,最大权值最小的生成树. 如何操作? 1.Pri ...

随机推荐

  1. python之路第二天

    为何要有操作系统 为了让程序员更轻松的完成命令电脑工作而存在的,控制硬件,服务于软件. 操作系统的位置 操作系统位于软件和硬件之间.操作系统由内核(运行于内核态,控制硬件)和系统调用(运行于用户态,为 ...

  2. (转)CSS3之pointer-events(屏蔽鼠标事件)属性说明

    我们在 HTML 开发时可能会遇到这样的情况:页面上有一些元素使用绝对定位布局,这些元素可能会遮盖住它们位置下方的某个元素的部分或者全部.默认情况下,下方元素被遮挡的部分是不会响应鼠标事件的. 但有时 ...

  3. java & python猜数字游戏对比

    1.java版 package day03; import java.util.Random;import java.util.Scanner; /** * 猜数字游戏 * 随机生成一个1-100之间 ...

  4. 51 Nod 1256 乘法逆元(数论:拓展欧几里得)

    1256 乘法逆元  基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 给出2个数M和N(M < N),且M与N互质,找出一个数K满足0 < K ...

  5. 微信jssdk分享功能开发

    先理解下分享: 在app端 ,经常能看见 分享按钮的功能,(分享给朋友,分享到朋友圈,分享到QQ空间等等): https://open.weixin.qq.com/(微信开发平台),这需要到开放平台注 ...

  6. C#异常断电后重新启动项目出现配置未初始化错误

    转到如截图中所示路径,将其下的数据删掉,就可以启动了.

  7. NEST - 编写布尔查询

    Writing bool queries Version:5.x 英文原文地址:Writing bool queries 在使用查询 DSL 时,编写 bool 查询会很容易把代码变得冗长.举个栗子, ...

  8. 如何在grails2.3.x中的fork模式下进行调试?-【grails】

    grails2.3.x中默认情况下运行模式被设置成了fork模式,在这种模式下,大家会发现设置了断点后无法进行中断.这是由于fork模式造成的,因为在fork模式下,JVM新起了一个进程,这样调试器就 ...

  9. js网页下载csv格式的表格

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. 微信获取地理位置转城市demo

    <script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.0.0.js ...