洛谷.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 ...
随机推荐
- 第八周学习总结-C#、C++
2018年9月2日 今天是小学期开始第三天,本周前几天看了看C#和C++,用C#窗体做了个计算器,然后还用Scratch做了一个贪吃蛇的脚本. 31号小学期开始,到今天我把A类基本做完了.一开始做通讯 ...
- WebStorm中常用的快捷键及使用技巧
------------------------------------- 近期整理了如下个人觉得比较常用的快捷键,也请前辈给予补充.多多指教. --------------------------- ...
- Java手动释放对象
伪代码 public void updateUser(BufferedWriter writer, BufferedReader reader) { List<User> array = ...
- Python变量的作用域
局部变量 局部变量是指在函数内部定义并使用的变量,他只在函数内部有效.即函数内部的名字只在函数运行时才会创建,在函数运行之前或者运行完毕之后,所有的名字就都不存在了.所以,如果在函数外部使用函数内部定 ...
- Command 'ifconfig' not found, but can be installed with: sudo apt install net-tools
然后按照错误信息安安装网络工具: sudo apt install net-tools shl@shl-tx:~$ sudo apt install net-tools正在读取软件包列表... 完成正 ...
- The error may exist in com/bjpowernode/dao/StudentDao.xml ### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderExcept
The error may exist in com/bjpowernode/dao/StudentDao.xml### Cause: org.apache.ibatis.builder.Builde ...
- EF Core Migration
//添加migrations dotnet ef migrations add [名称] //根据model更新sql表结构 dotnet ef database update //删除最新的migr ...
- javascript扩充基本类型的功能
可以通过给Function.prototype增加方法来使得该方法对所有函数可用. 通过给Function.prototype增加一个method方法,下次给对象增加方法的时候就不必键入prototy ...
- HDU 5977 Garden of Eden (树形dp+快速沃尔什变换FWT)
CGZ大佬提醒我,我要是再不更博客可就连一月一更的频率也没有了... emmm,正好做了一道有点意思的题,就拿出来充数吧=.= 题意 一棵树,有 $ n (n\leq50000) $ 个节点,每个点都 ...
- 【Android】ImageView ScaleType属性值
ImageView.ScaleType / android:scaleType值的意义区别: CENTER /center 按图片的原来size居中显示,当图片长/宽超过View的长/宽,则截取图片的 ...