先存代码

AC自动机(简单版)

  

#include<bits/stdc++.h>
#define maxn 1000007
using namespace std;
int n,ans;
int tr[maxn][28],val[maxn],cnt,fail[maxn];
char mod[maxn],tx[maxn];
queue<int >q; void build(char *a){
int now=0;
for(int i=0;a[i];i++){
if(!tr[now][a[i]-'a']) tr[now][a[i]-'a']=++cnt;
now=tr[now][a[i]-'a'];
}
val[now]++;
}//建树 void AC(){
for(int i=0;i<26;i++) if(tr[0][i]) q.push(tr[0][i]);//26个字母跑
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<26;i++){
if(tr[u][i]) fail[tr[u][i]]=tr[fail[u]][i],q.push(tr[u][i]);//调取指针
else tr[u][i]=tr[fail[u]][i];//建立“虚边”——指向失配指针的i边
//这里已经改变了trie图
}
}
} int query(char *t){
int ol=0,u=0;
for(int i=0;t[i];i++){
u=tr[u][t[i]-'a'];
for(int j=u;j&&val[j]!=-1;j=fail[j])
ol+=val[j],val[j]=-1;//fail跳(这样其实很慢)
}
return ol;
} int main(){
// freopen("cin.in","r",stdin);
// freopen("co.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%s",mod),build(mod);
AC();
scanf("%s",tx);ans=query(tx);
printf("%d\n",ans);
}

AC自动机(加强版)

#include<bits/stdc++.h>
#define maxn 1000007
using namespace std;
int T,n,ans;
char mod[maxn][100],tx[maxn]; namespace AC{
int tr[maxn][27],fail[maxn],tot;
int cnt,val[maxn],num[maxn];
void Init(){
memset(tr,0,sizeof(tr));
memset(num,0,sizeof(num));
memset(fail,0,sizeof fail);
memset(val,0,sizeof val);
cnt=ans=0;
}
void insert(char *s,int id){
int now=0;
for(int i=0;s[i];i++){
if(!tr[now][s[i]-'a']) tr[now][s[i]-'a']=++cnt;
now=tr[now][s[i]-'a'];
}
val[now]=id;//记录id,这个不怕覆盖
}
queue<int >q;
void build(){
for(int i=0;i<26;i++) if(tr[0][i]) q.push(tr[0][i]);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<26;i++)
if(tr[u][i]) fail[tr[u][i]]=tr[fail[u]][i],q.push(tr[u][i]),cerr<<fail[tr[u][i]]<<endl;
else tr[u][i]=tr[fail[u]][i];
}
}
void query(char *t){
int u=0;
for(int i=0;t[i];i++){
u=tr[u][t[i]-'a'];
for(int j=u;j;j=fail[j])
if(val[j]) num[val[j]]++,ans=max(ans,num[val[j]]);
}//还是跳,不过记录的不一样而已
printf("%d\n",ans);
for(int i=1;i<=n;i++) if(ans==num[i]) printf("%s\n",mod[i]);
}
} int main(){
scanf("%d",&n);
while(n){
AC::Init();
for(int i=1;i<=n;i++) scanf("%s",mod[i]),AC::insert(mod[i],i);
AC::build();
scanf("%s",tx);
AC::query(tx);
scanf("%d",&n);
}
}

AC自动机(二次加强版)

#include<bits/stdc++.h>
#define maxn 2000007
using namespace std;
int n;
char mod[maxn],tx[maxn];
int fail[maxn],tr[maxn][27],val[maxn],num[maxn];
int id[maxn],cnt,in[maxn],to[maxn]; void insert(char *a,int idx){
int now=0;
for(int i=0;a[i];i++){
if(!tr[now][a[i]-'a']) tr[now][a[i]-'a']=++cnt;
now=tr[now][a[i]-'a'];
}
val[now]++;id[idx]=now;//记录
} queue<int >q; void build(){
for(int i=0;i<26;i++) if(tr[0][i]) q.push(tr[0][i]);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<26;i++){
if(tr[u][i]) fail[tr[u][i]]=tr[fail[u]][i],q.push(tr[u][i]),in[fail[tr[u][i]]]++;
else tr[u][i]=tr[fail[u]][i];
}
}
} void query(char *t){
int u=0;
for(int i=0;t[i];i++)
u=tr[u][t[i]-'a'],num[u]++;
} void topu(){
for(int i=1;i<=cnt;i++) if(!in[i]) q.push(i);
while(!q.empty()){
int u=q.front(),v=fail[u];q.pop();
num[v]+=num[u];--in[v];
if(!(in[v])) q.push(v);
}
}//这里是跟题解学的topu,效率也挺高 int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%s",mod),insert(mod,i);
build();
scanf("%s",tx);query(tx);
topu();
for(int i=1;i<=n;i++) printf("%d\n",num[id[i]]);
}

单词

#include<bits/stdc++.h>
#define maxn 2000007
using namespace std;
int n;
char mod[maxn],tx[maxn],c[maxn];
int fail[maxn],tr[maxn][28],val[maxn],num[maxn];
int id[maxn],cnt,in[maxn],tot; void insert(char *a,int idx){
int now=0;
for(int i=0;a[i];i++){
if(!tr[now][a[i]-'a']) tr[now][a[i]-'a']=++cnt;
now=tr[now][a[i]-'a'];
}
val[now]++;id[idx]=now;
} queue<int >q; void build(){
for(int i=0;i<27;i++) if(tr[0][i]) q.push(tr[0][i]);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<27;i++){
if(tr[u][i]) fail[tr[u][i]]=tr[fail[u]][i],q.push(tr[u][i]),in[fail[tr[u][i]]]++;
else tr[u][i]=tr[fail[u]][i];
}
}
} void query(char *t){
int u=0;
for(int i=0;t[i];i++)
u=tr[u][t[i]-'a'],num[u]++;
} void topu(){
for(int i=1;i<=cnt;i++) if(!in[i]) q.push(i);
while(!q.empty()){
int u=q.front(),v=fail[u];q.pop();
num[v]+=num[u];--in[v];
if(!(in[v])) q.push(v);
}
} void work(char *a,char *b){
int len1=strlen(a),len2=strlen(b);
for(int i=len1;i<len1+len2;i++)
a[i]=b[i-len1];
} int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%s",c),work(mod,c),
tot=strlen(mod),insert(c,i),mod[tot++]='{';
build();
query(mod);topu();
for(int i=1;i<=n;i++) printf("%d\n",num[id[i]]);
}

AC自动机——看似KMP在跑,其实fail在跳的更多相关文章

  1. AC自动机及KMP练习

    好久都没敲过KMP和AC自动机了.以前只会敲个kuangbin牌板子套题.现在重新写了自己的板子加深了印象.并且刷了一些题来增加自己的理解. KMP网上教程很多,但我的建议还是先看AC自动机(Trie ...

  2. 2017多校第8场 HDU 6138 Fleet of the Eternal Throne AC自动机或者KMP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6138 题意:给n个串,每次询问x号串和y号串的最长公共子串的长度,这个子串必须是n个串中某个串的前缀 ...

  3. AC自动机讲解

    今天花了半天肝下AC自动机,总算啃下一块硬骨头,熬夜把博客赶出来.. 正如许多博客所说,AC自动机看似很难很妙,而事实上不难,但的确很妙.笼统地说,AC自动机=Trie+KMP,但是仅仅知道这个并没有 ...

  4. 初学AC自动机

    前言 一直听说\(AC\)自动机是一个很难很难的算法,而且它不在\(NOIP\)提高组范围内(这才是关键),所以我一直没去学. 最近被一些字符串题坑得太惨,于是下定决心去学\(AC\)自动机. 简介 ...

  5. AC自动机简明教程

    不会kmp和Trie树的请点击右上角X. AC自动机与kmp的唯一区别便是从单模式串变成了多模式串. 那么与kmp相同,AC自动机中的fail指针是指向当前状态的最长后缀. 当然这个后缀要在Trie树 ...

  6. AC自动机讲解超详细

    begin:2019/5/2 感谢大家支持! AC自动机详细讲解 AC自动机真是个好东西!之前学KMP被Next指针搞晕了,所以咕了许久都不敢开AC自动机,近期学完之后,发现AC自动机并不是很难,特别 ...

  7. 【模版 Luogu P3808/P3796/P5357】AC自动机(简论)

    浙江集训Day9,没有出任何实质性成果,只好把昨天打完的板子记一下. 该博客基于luogu的三道模版题.只有一个大致的讲解,主要提供代码给自己参考. ------------------------- ...

  8. 「笔记」AC 自动机

    目录 写在前面 定义 引入 构造 暴力 字典图优化 匹配 在线 离线 复杂度 完整代码 例题 P3796 [模板]AC 自动机(加强版) P3808 [模板]AC 自动机(简单版) 「JSOI2007 ...

  9. AC 自动机学习笔记

    虽然 NOIp 原地爆炸了,目前进入 AFO 状态,但感觉省选还是要冲一把,所以现在又来开始颓字符串辣 首先先复习一个很早很早就学过但忘记的算法--自动 AC AC自动机. AC 自动机能够在 \(\ ...

随机推荐

  1. linux环境下oracle 11g 静默安装

    安装环境 Linux服务器:oracle linux 6.6 64位 Oracle服务器:Oracle11gR2 64位 系统要求 1.Linux安装Oracle系统要求 系统要求 说明 内存 必须高 ...

  2. Head First 设计模式 —— 13. 代理 (Proxy) 模式

    思考题 如何设计一个支持远程方法调用的系统?你要怎样才能让开发人员不用写太多代码?让远程调用看起来像本地调用一样,毫无瑕疵? P435 已经接触过 RPC 了,所以就很容易知道具体流程:客户端调用目标 ...

  3. ansible 安装和使用

                                ansible 安装和使用   ## 安装epel 源: rpm -ivh https://dl.fedoraproject.org/pub/e ...

  4. 关联实现上-jsonpath取值

    举例子: demo01.py import jsonimport requestsimport jsonpathsession = requests.session()get_param_dict={ ...

  5. Oracle Rac to Rac One Node

    =~=~=~=~=~=~=~=~=~=~=~= PuTTY log 2020.01.14 20:05:12 =~=~=~=~=~=~=~=~=~=~=~= [oracle@rac01 ~]$ srvc ...

  6. Junit测试和反射

    Junit单元测试 测试分类 黑盒测试:不需要写代码,给输入值,看程序能否得到输出期望值. 白盒测试:需要些代码,关注程序具体的执行流程. Junit的使用 步骤 定义一个测试类(测试用例). 定义测 ...

  7. gRPC-go源码(1):连接管理

    1 写在前面 在这个系列的文章中,我们将会从源码的层面学习和理解gRPC. 整个系列的文章的计划大概是这样的:我们会先从客户端开始,沿着调用路径逐步分析到服务端,以模块为粒度进行学习,考虑这个模块是为 ...

  8. code-server scala error: object apache is not a member of package org

    原因是scala缺少包,需要把spark或对应的包放入scala目录下的lib,然后重启主机,在terminal输入reboot即可. 如果不重启主机,则在交互式编程中可以成功import.但是直接在 ...

  9. git的使用学习笔记--项目版本操作

    一.使用场景 版本回退:上线失败--需要回退到上个版本 二.操作 先编辑  vim text.txt git status git add .       这个命令能看到所有的增加操作 git com ...

  10. python 招聘数据分析

    导入包 import pandas as pd import numpy as np import matplotlib.pyplot as plt 读文件 df=pd.read_csv(r'C:\U ...