洛谷.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 ...
 
随机推荐
- bzoj 4011
			
看了好多篇题解才看懂的题,我实在太菜了... 首先根据一个我不知道的算法,可以证明在没有加入新的边的时候,原图的所有生成树的方案数就是所有点(除1以外)的度之积 那么在新加入这条边之后,我们仍然可以这 ...
 - js中onload和jQuery中的ready区别
			
window.onload必须等到页面内包括图片的所有元素加载完毕后才能执行. ------>不能写多个(如果有多个,只会执行一个) $(document).ready()是DOM结构绘制完毕后 ...
 - Fidder 请求信息颜色的含义
			
颜色 含义 红色 HTTP状态错误 黄色 HTTP状态需用户认证 灰色 数据流类型CONNECT 或 响应内容是图片 紫色 响应内容是CSS文件 蓝色 响应内容是HTML 绿色 响应内容是Script ...
 - 20165206 2017-2018-2 《Java程序设计》第七周学习总结
			
20165206 2017-2018-2 <Java程序设计>第七周学习总结 教材学习内容总结 MySqL:是世界上最流行的开源数据管理系统. 配置启动MySQL. 连接数据库:Conne ...
 - 20165323 2017-2018-2 《Java程序设计》课程总结
			
一.每周作业链接汇总 预备作业1:20165323 我期望的师生关系 预备作业2:20165323 学习基础与C语言学习心得 预备作业3:20165323 预备作业三 第一周作业:20165323&l ...
 - 安装和强行卸载fuse
			
先卸载 yum list fuse yum --setopt=tsflags=noscripts remove fuse.x86_64 安装 yum install automake gcc-c++ ...
 - 【转】Android逆向入门流程
			
原文:https://www.jianshu.com/p/71fb7ccc05ff 0.写在前面 本文是笔者自学笔记,以破解某目标apk的方式进行学习,中间辅以原理性知识,方便面试需求. 参考文章的原 ...
 - Tarjan算法【强连通分量】
			
转自:byvoid:有向图强连通分量的Tarjan算法 Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树.搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断 ...
 - Tychonov Theorem
			
(Remark: The proof presented in this post is a reorganization and interpretation of that given by Ja ...
 - Introduction to boundary integral equations in BEM
			
Boundary element method (BEM) is an effective tool compared to finite element method (FEM) for resol ...