YBT 2.4 AC自动机
其实这个专题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自动机相关推荐
- Aho-Corasick 多模式匹配算法(AC自动机) 的算法详解及具体实现
多模式匹配 多模式匹配就是有多个模式串P1,P2,P3-,Pm,求出所有这些模式串在连续文本T1-.n中的所有可能出现的位置. 例如:求出模式集合{"nihao","ha ...
- 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组
[BZOJ2434][NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P ...
- AC自动机算法及模板
AC自动机算法及模板 2016-05-08 18:58 226人阅读 评论(0) 收藏 举报 分类: AC自动机(1) 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 关于 ...
- Keywords Search AC自动机QAQ
AC自动机,一直以来都以为是一个非常高大上的算法,其实它还真的挺高大上的. 首先来说,ac自动机的思想与kmp类似,需要自己模拟来理解. 给两个博客: http://www.cppblog.com/m ...
- 字符串匹配算法 -- AC自动机 基于Trie树的高效的敏感词过滤算法
文章目录 1. 算法背景 2. AC自动机实现原理 2.1 构建失败指针 2.2 依赖失败指针过滤敏感词 3. 复杂度及完整代码 1. 算法背景 之前介绍过单模式串匹配的高效算法:BM和KMP 以及 ...
- 【Luogu3041】视频游戏的连击(AC自动机,动态规划)
题面链接 题解 首先构建出AC自动机 然后在AC自动机上面跑DP 转移很显然从Trie树的节点跳到他的儿子节点 但是要注意一个问题, 在计算的时候,每一个节点加入后能够 造成的贡献 要加上他的子串的贡 ...
- HDU2896(AC自动机模版题)
AC自动机模版题: 方法一:超时 #include<iostream> #include<algorithm> #include<cstring> #include ...
- HDU2222(AC自动机模版题)
AC自动机是Trie树和KMP的结合物,但是其实KMP在这里体现了思想,而Trie树才是最重要的,要想学懂AC自动机,学习Trie树是必须的,这些是自己在学习AC自动机的个人看法,我也是在网上学习了大 ...
- 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}的序列,现在裁判开始投掷骰子,并且把每次的 ...
最新文章
- 信息化项目管理制度_华为内部几近满分的项目管理PPT,收走!
- SpringBoot学习:整合shiro(身份认证和权限认证),使用EhCache缓存
- Java内存模型深度解析:重排序 --转
- 【转载】Spring Boot 过滤器、监听器、拦截器的使用
- 无法读取源文件或磁盘_raid磁盘阵列作用
- matlab调用python_从MATLAB调用Python函数
- Oracle 移动数据文件的操作方法
- PHP面向对象重要知识点----------第一部分
- TOPSIS法——利用原始数据进行综合评价
- 鸿蒙形容欣欣向荣发展,形容发展迅速的12个成语
- 总结揭露黑客入侵网站的手法
- 麻省理工MIT计算机课程表
- 彻底删除Cygwin
- ESP8266 NodeMCU Web 服务器:在仪表盘中显示传感器读数
- 2.14Python标准库使用案例:使用turtle绘制奥林匹克五环
- (一)论文阅读 | 目标检测之CornerNet
- 《中国人史纲》读书笔记:第四章 半信史时代 第五章 信史时代
- 神经网络是线性分类器吗,有哪些典型的神经网络
- C语言图书馆管理系统
- 自然辩证法复习题 1
热门文章
- python 模糊匹配_Case2:模糊匹配工具
- 桌面计算机怎么覆盖文件,恢复被覆盖的文件_恢复被覆盖的桌面文件
- 编写计算机取余程序_必须收藏,2020年专升本计算机常考知识点总结,抓分的关键点...
- 必须声明标量变量 @列名
- 软件测试方法进行调优,性能测试调优过程
- centos jupyter 安装_centos6.4安装 jupyter-notebook
- 可以解压日文的软件_日文换成中文字体就不好看?我偏不信这个邪!
- 域控服务器降级失败,降级域控制器时出错 - Windows Server | Microsoft Docs
- java语言程序设计考题_《JAVA语言程序设计》期末考试试题及答案6(应考必备题库)...
- 光流(二)--光流算法