其实这个专题NOIP几乎不考

AC自动机,就是能让题自动AC的东西,是不是十分神奇

对的,就是这么神奇

AC自动机是解决多模式串与文本串匹配的问题

是KMP+Trie树的结合,也是一个毒瘤算法

Keywords Search

link

此题是AC自动机的板子,刚才说过AC自动机是解决匹配问题的,这道题便如此

板子题,记录结尾即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{int f=1,ans=0;char c;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}return f*ans;
}
int t,n;
int bo[500005],tot,ch[500005][26];
char str[1000001];
void insert(char *str)
{int u=1;int len=strlen(str);for(int i=0;i<len;i++){int c=str[i]-'a';if(ch[u][c]==0) ch[u][c]=++tot;u=ch[u][c];    }bo[u]++;return;
}
int nex[500005],que[500005];
void bfs()
{que[1]=1,nex[1]=0;int head=1,tail=1;while(head<=tail){int t=que[head]; head++;for(int i=0;i<=25;i++){if(ch[t][i]==0) ch[t][i]=ch[nex[t]][i];else{que[++tail]=ch[t][i];int v=nex[t];nex[ch[t][i]]=ch[v][i];}}}
}
int ans;
void find(char *str)
{int u=1,k;int len=strlen(str);for(int i=0;i<len;i++){int c=str[i]-'a';k=ch[u][c],u=ch[u][c];while(k>1){ans+=bo[k];bo[k]=0;k=nex[k];}}return;
}
int main()
{t=read();while(t--){ans=0;tot=1;memset(ch,0,sizeof(ch));memset(bo,0,sizeof(bo));for(int i=0;i<=25;i++) ch[0][i]=1;n=read();for(int i=1;i<=n;i++) {scanf("%s",str);insert(str);}bfs();scanf("%s",str); find(str);cout<<ans<<endl;}
}

View Code

玄武密码

link

此题求模式串在文本串前缀最大匹配长度

所以让文本串在AC自动机上走一遍,用flag记录经过的点

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{int f=1,ans=0;char c;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}return f*ans;
}
int n,m,le[100001];
char cx(char u)
{if(u=='E') return '0';if(u=='S') return '1';if(u=='W') return '2';if(u=='N') return '3';
}
int fa[10000001],ch[1000001][4],tot;
bool flag[1000001];
char str[1110];
int nex[1000010];
int que[1000010];
char s[10000010];
int son[100001];
void insert(char *str,int an)
{int u=1;int len=strlen(str);le[an]=len;for(int i=0;i<len;i++){int c=str[i]-'0';if(ch[u][c]==0) ch[u][c]=++tot,fa[tot]=u;u=ch[u][c];}son[an]=u;return;
}void bfs()
{nex[1]=0,que[1]=1;int head=1,tail=1;while(head<=tail){int x=que[head];head++;for(int i=0;i<4;i++){if(ch[x][i]==0) ch[x][i]=ch[nex[x]][i];else{que[++tail]=ch[x][i];nex[ch[x][i]]=ch[nex[x]][i];}}}return;
}
int ls;
void find(char *s)
{int u=1,k;for(int i=0;i<ls;i++){int c=s[i]-'0';k=ch[u][c];while(k>1) {if(flag[k]) break;flag[k]=1;k=nex[k];}u=ch[u][c];}return;
}
int work(int an)
{int u=son[an];for(int i=le[an];i>=1;i--){if(flag[u]) return i;u=fa[u];}return 0;
}
int main()
{memset(ch,0,sizeof(ch));tot=1;n=read(),m=read();scanf("%s",s); for(int i=0;i<4;i++) ch[0][i]=1;ls=strlen(s);for(int i=0;i<ls;i++) s[i]=cx(s[i]);for(int i=0;i<4;i++) ch[0][i]=1;for(int i=1;i<=m;i++){       scanf("%s",str);int l=strlen(str);for(int j=0;j<l;j++) str[j]=cx(str[j]);insert(str,i);}bfs();find(s);for(int i=1;i<=m;i++) printf("%d\n",work(i));//cout<<work(i)<<endl;
}

View Code

Censoring

link

也是让文本串在AC自动机上跑,然后记录一下位置

#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{int f=1,ans=0;char c;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}return f*ans;
}
char str[1000011];
int n;
int ch[2600001][26],tot;
char s[1000011];
int que[2600001],nex[2600001];
int bo[2600001];
void insert(char *s)
{int len=strlen(s);int u=1;for(int i=0;i<len;i++){int c=s[i]-'a';if(ch[u][c]==0) ch[u][c]=++tot;u=ch[u][c];}bo[u]=len;return;
}
void bfs()
{int head=1,tail=1;que[1]=1,nex[1]=0;while(head<=tail){int x=que[head];head++;for(int i=0;i<26;i++){if(ch[x][i]==0) ch[x][i]=ch[nex[x]][i];else{que[++tail]=ch[x][i];nex[ch[x][i]]=ch[nex[x]][i];}}}return;
}
int stk1[26000001],stk2[26000001];
void find(char *str)
{int u=1;int tot=0;int len=strlen(str);for(int i=0;i<len;i++){int c=str[i]-'a';u=ch[u][c];stk1[++tot]=u;stk2[tot]=i;while(bo[u]) {tot-=bo[u];u= stk1[tot];}}for(int i=1;i<=tot;i++) cout<<str[stk2[i]];cout<<endl;
}
int main()
{tot=1;for(int i=0;i<26;i++) ch[0][i]=1;scanf("%s",str);n=1;for(int i=1;i<=n;i++){scanf("%s",s);insert(s);}bfs();find(str);
}

View Code

单词(待补此坑)

最短母串(待补此坑)

病毒

link

此题是不让文本串在AC自动机上跑到每个模式串的末尾

所以想这个问题,如果说你有无穷长度的文本串

在AC自动机上跑着,但是不让他经过末尾

所以说这个图是有环的,AC自动机不是因为节省时间直接相连nex吧,所以好像这个叫做fail图

所以看一下在AC自动机中不经过每个字符串尾端是否有环即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
inline int read()
{int f=1,ans=0;char c;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}return f*ans;
}
char s[900001];
int tot,st[9000001];
int ch[9000001][3];
int n;
int quee[3000001],nex[3000001];
void insert(char *s)
{int len=strlen(s),u=1;for(int i=0;i<len;i++) {int c=s[i]-'0';if(!ch[u][c]) ch[u][c]=++tot;u=ch[u][c];}st[u]=1;return;
}
void bfs()
{int head=1,tail=1;quee[1]=1,nex[1]=0;while(head<=tail){int x=quee[head];head++;for(int i=0;i<=1;i++){if(ch[x][i]==0) ch[x][i]=ch[nex[x]][i];else{quee[++tail]=ch[x][i];nex[ch[x][i]]=ch[nex[x]][i];if(st[nex[ch[x][i]]]) st[ch[x][i]]++;  }}}return;
}
int vis1[300011],vis2[300011];
bool flag;
void dfs(int f)
{if(flag) return;vis2[f]=1;for(int i=0;i<=1;i++){int s=ch[f][i];if(flag) return;if(st[s]) continue;if(vis2[s]) {flag=1;cout<<"TAK";return;}if(flag) return;if(vis1[s]) continue;vis1[s]=1;dfs(s);}vis2[f]=0;
}
int main()
{tot=1;n=read();for(int i=0;i<=1;i++) ch[0][i]=1;for(int i=1;i<=n;i++) scanf("%s",s),insert(s);bfs();flag=false;dfs(0);if(flag==0) cout<<"NIE";return 0;
}
/*
2
1
0
*/

View Code

文本生成器

link

第一次在AC自动机上跑dp

想一个问题,如果这个有m长度的文本串符合条件的话,他至少是一个模式的母串吧

你怎么去统计呢,有可能是一个,两个,三个,四个~~~

在数学上有一种想法是退而求进,所以可以把这道题转换成有多少个无法模式串匹配的情况

这时候求的就是0了,然后去拿总可能-这种可能便是答案

为什么说这一道题是dp呢,因为满足dp的思想了

dp[i]为长度为i有多少个

但是无法往前推

所以再加一维,加什么呢

很容易想到是访问在哪个节点吧

所以dp模型就已经定下来了

dp[i][j]表示现在长度为i,节点是j共有多少个串

AC自动机有什么用呢,其实就是建图有用

将字符串转换成一张图

不让他走末尾节点

所以现在就有一个要注意的坑点了

***当你找到一点x,若此点的nex是一个字符串的结尾,所以这个x其实就是一个病毒了

其实就是每人对nex理解了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mod 10007
using namespace std;
inline long long read()
{long long f=1,ans=0;char c;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}return f*ans;
}
long long n,m,tot,u,ch[900001][26],bo[900001];
char s[3000001];
void insert(char *s)
{long long len=strlen(s),u=1;for(long long i=0;i<len;i++){long long c=s[i]-'A';if(!ch[u][c]) ch[u][c]=++tot;u=ch[u][c];}bo[u]=1;return;
}
long long que[3000001],nex[3000001];
void bfs()
{long long head=1,tail=1;que[1]=1,nex[1]=0;while(head<=tail){long long xx=que[head];head++;for(long long i=0;i<26;i++){if(ch[xx][i]==0) ch[xx][i]=ch[nex[xx]][i];else{que[++tail]=ch[xx][i];nex[ch[xx][i]]=ch[nex[xx]][i]; bo[ch[xx][i]]|=bo[ch[nex[xx]][i]];}}}return;
}
long long dp[151][300001];
int main()
{for(long long i=0;i<26;i++) ch[0][i]=1;tot=1;n=read(),m=read();for(long long i=1;i<=n;i++){scanf("%s",s);insert(s);}bfs();dp[0][1]=1;for(long long i=1;i<=m;i++) for(long long j=1;j<=tot;j++)for(long long z=0;z<26;z++) if(!bo[ch[j][z]]) dp[i][ch[j][z]]+=dp[i-1][j],dp[i][ch[j][z]]%=mod;long long ans=0;for(long long i=1;i<=tot;i++) ans+=dp[m][i],ans%=mod;long long sum=1;for(long long i=1;i<=m;i++) sum*=26,sum%=mod;cout<<(sum-ans+mod)%mod;
}

View Code

转载于:https://www.cnblogs.com/si-rui-yang/p/9709479.html

YBT 2.4 AC自动机相关推荐

  1. Aho-Corasick 多模式匹配算法(AC自动机) 的算法详解及具体实现

    多模式匹配 多模式匹配就是有多个模式串P1,P2,P3-,Pm,求出所有这些模式串在连续文本T1-.n中的所有可能出现的位置. 例如:求出模式集合{"nihao","ha ...

  2. 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组

    [BZOJ2434][NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P ...

  3. AC自动机算法及模板

    AC自动机算法及模板 2016-05-08 18:58 226人阅读 评论(0) 收藏 举报  分类: AC自动机(1)  版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 关于 ...

  4. Keywords Search AC自动机QAQ

    AC自动机,一直以来都以为是一个非常高大上的算法,其实它还真的挺高大上的. 首先来说,ac自动机的思想与kmp类似,需要自己模拟来理解. 给两个博客: http://www.cppblog.com/m ...

  5. 字符串匹配算法 -- AC自动机 基于Trie树的高效的敏感词过滤算法

    文章目录 1. 算法背景 2. AC自动机实现原理 2.1 构建失败指针 2.2 依赖失败指针过滤敏感词 3. 复杂度及完整代码 1. 算法背景 之前介绍过单模式串匹配的高效算法:BM和KMP 以及 ...

  6. 【Luogu3041】视频游戏的连击(AC自动机,动态规划)

    题面链接 题解 首先构建出AC自动机 然后在AC自动机上面跑DP 转移很显然从Trie树的节点跳到他的儿子节点 但是要注意一个问题, 在计算的时候,每一个节点加入后能够 造成的贡献 要加上他的子串的贡 ...

  7. HDU2896(AC自动机模版题)

    AC自动机模版题: 方法一:超时 #include<iostream> #include<algorithm> #include<cstring> #include ...

  8. HDU2222(AC自动机模版题)

    AC自动机是Trie树和KMP的结合物,但是其实KMP在这里体现了思想,而Trie树才是最重要的,要想学懂AC自动机,学习Trie树是必须的,这些是自己在学习AC自动机的个人看法,我也是在网上学习了大 ...

  9. AC自动机 + 概率dp + 高斯消元 --- HDU 5955 or 2016年沈阳icpc H [AC自动机 + 概率dp + 高斯消元]详解

    题目链接 题目大意: 就是有NNN个人,每个人都会猜一个长度为LLL的只包含{1,2,3,4,5,6}\{1,2,3,4,5,6\}{1,2,3,4,5,6}的序列,现在裁判开始投掷骰子,并且把每次的 ...

最新文章

  1. 信息化项目管理制度_华为内部几近满分的项目管理PPT,收走!
  2. SpringBoot学习:整合shiro(身份认证和权限认证),使用EhCache缓存
  3. Java内存模型深度解析:重排序 --转
  4. 【转载】Spring Boot 过滤器、监听器、拦截器的使用
  5. 无法读取源文件或磁盘_raid磁盘阵列作用
  6. matlab调用python_从MATLAB调用Python函数
  7. Oracle 移动数据文件的操作方法
  8. PHP面向对象重要知识点----------第一部分
  9. TOPSIS法——利用原始数据进行综合评价
  10. 鸿蒙形容欣欣向荣发展,形容发展迅速的12个成语
  11. 总结揭露黑客入侵网站的手法
  12. 麻省理工MIT计算机课程表
  13. 彻底删除Cygwin
  14. ESP8266 NodeMCU Web 服务器:在仪表盘中显示传感器读数
  15. 2.14Python标准库使用案例:使用turtle绘制奥林匹克五环
  16. (一)论文阅读 | 目标检测之CornerNet
  17. 《中国人史纲》读书笔记:第四章 半信史时代 第五章 信史时代
  18. 神经网络是线性分类器吗,有哪些典型的神经网络
  19. C语言图书馆管理系统
  20. 自然辩证法复习题 1

热门文章

  1. python 模糊匹配_Case2:模糊匹配工具
  2. 桌面计算机怎么覆盖文件,恢复被覆盖的文件_恢复被覆盖的桌面文件
  3. 编写计算机取余程序_必须收藏,2020年专升本计算机常考知识点总结,抓分的关键点...
  4. 必须声明标量变量 @列名
  5. 软件测试方法进行调优,性能测试调优过程
  6. centos jupyter 安装_centos6.4安装 jupyter-notebook
  7. 可以解压日文的软件_日文换成中文字体就不好看?我偏不信这个邪!
  8. 域控服务器降级失败,降级域控制器时出错 - Windows Server | Microsoft Docs
  9. java语言程序设计考题_《JAVA语言程序设计》期末考试试题及答案6(应考必备题库)...
  10. 光流(二)--光流算法