想知道484每个萌新oier在最初知道AC自动机的时候都会理解为自动AC稽什么的,,,反正我记得我当初刚知道这个东西的时候,我以为是什么神仙东西$hhhhh$

首先要学AC自动机,就要先学会俩知识点:

trie树和kmp(我记得我都写了学习笔记,,,然而写得太烂了不想放上来了,,,网上随便搜篇题解都写得比我好的样子TT

好的那就当做已经掌握了这俩了来学习AC自动机趴!

首先要知道AC自动机是解决什么东西的嘛QwQ

kmp是一对一嘛,就是说一个字符串匹配一个字符串

然后AC自动机就是解决它没有解决的问题——一对多,一个字符串匹配多个字符串

这方面的题目比较多问法什么的也比较多我就以板子题1为例学下这个知识点好了QAQ

首先我们就读入所有模式串,建一棵trie树

然后就建fail指针

先说说fail指针是干什么的趴QwQ

举个eg好了,假如模式串有ace acd say she shr her ced 然后文本串是aced

于是构出来的trie树长这样(,,,图咕了$QAQ$

假如我们现在再匹配ace,那就当匹配到e之后就没有辣,那我们就找有麻油还能匹配的呢

那我们就和之前想kmp的时候一样,想着怎么利用之前做了的事儿呢,就想到,假如我能匹配ace,我就一定也能匹配ce,就一定也能匹配e这样子的对趴

所以我们就找啊,找trie树上有麻油一个点它及它之前的字符串和ace的后缀相同的

这个就是fail指针的作用了——记录每个点的表示的字符串的最长后缀指向哪个点

明白了麻油!我jio得还挺好理解的!

哦对了我好像没有解释为什么是最长后缀,,,?其实我jio得挺显然的?就是因为假如我有个ac还有个a,那我如果指向ac之后等ac匹配完了自然会去a的,可是如果指向的是a它不可能再指向ac了

get?

好大概思路就是这样的,具体实现和代码等下再说趴,,,QAQ

#include<bits/stdc++.h>
using namespace std;
#define ll int
#define rp(i,x,y) for(register ll i=x;i<=y;++i) const ll N=;
ll n,cnt,as;
struct tre{ll ed,nxt[],fail;tre(){ed=;memset(nxt,,sizeof(nxt));fail=;}}tr[N]; inline ll read()
{
register char ch=getchar();register ll x=;register bool y=;
while(ch!='-' && (ch>'' || ch<''))ch=getchar();
if(ch=='-')ch=getchar(),y=;
while(ch>='' && ch<='')x=(x<<)+(x<<)+(ch^''),ch=getchar();
return y?x:-x;
}
inline void bd(string x)
{
ll lth=x.length()-,nwtr=;
rp(i,,lth){if(tr[nwtr].nxt[x[i]-'a'+]==)tr[nwtr].nxt[x[i]-'a'+]=++cnt;nwtr=tr[nwtr].nxt[x[i]-'a'+];}
++tr[nwtr].ed;
}
inline void fl()
{
queue<ll>Q;
rp(i,,)if(tr[].nxt[i])Q.push(tr[].nxt[i]);
while(!Q.empty())
{
ll nw=Q.front();Q.pop();
rp(i,,)
{
if(tr[nw].nxt[i]){tr[tr[nw].nxt[i]].fail=tr[tr[nw].fail].nxt[i];Q.push(tr[nw].nxt[i]);}
else tr[nw].nxt[i]=tr[tr[nw].fail].nxt[i];
}
}
}
inline void zdj(string str)
{
ll lth=str.length()-,nw=;
rp(i,,lth)
{
nw=tr[nw].nxt[str[i]-'a'+];
for(ll t=nw;t && tr[t].ed!=-;t=tr[t].fail)
{
as+=tr[t].ed;
tr[t].ed=-;
}
}
printf("%d\n",as);
} int main()
{
n=read();rp(i,,n){string str;cin>>str;bd(str);}fl();
string str;cin>>str;zdj(str);
return ;
}

这题要注意下,,,我只开大了点儿就MLE了QAQ!

umm我想了下,把几个板子题都放这儿好了QAQ

这是板子2号

这题差不多啊,就先把trie树建起来,fail按套路求一下,然后注意一下的是计数的时候有个小技巧,就是可以让是结尾的节点的end=单词号,非结尾的=0,然后每次在文本串中扫到的时候就直接as[end]++就好了,没了

哦还有一个,,,题解第二个的方法似乎很妙,一个优化,一个树上dp,有时间再搞,QAQ

放下代码QAQ

#include<bits/stdc++.h>
using namespace std;
#define ll int
#define rp(i,x,y) for(register ll i=x;i<=y;++i) const ll N=,M=;
ll n,cnt,as;
struct tre
{
ll ed,nxt[],fail,cs;
void clr(){ed=;memset(nxt,,sizeof(nxt));fail=;}
}tr[N];
struct ans{ll pos,as;void clr(){as=;pos=;}}ass[M];
bool gdgs=;
string str[M]; inline ll read()
{
register char ch=getchar();register ll x=;register bool y=;
while(ch!='-' && (ch>'' || ch<''))ch=getchar();
if(ch=='-')ch=getchar(),y=;
while(ch>='' && ch<='')x=(x<<)+(x<<)+(ch^''),ch=getchar();
return y?x:-x;
}
inline bool cmp(ans gd,ans gs){return gd.as==gs.as?gd.pos<gs.pos:gd.as>gs.as;}
inline void bd(ll nm)
{
cin>>str[nm];ass[nm].clr();ass[nm].pos=nm;ll lth=str[nm].length()-,nw=;
rp(i,,lth)
{
if(tr[nw].nxt[str[nm][i]-'a'+]==)tr[nw].nxt[str[nm][i]-'a'+]=++cnt,tr[cnt].clr();
nw=tr[nw].nxt[str[nm][i]-'a'+];
}
tr[nw].ed=nm;
}
inline void fl()
{
queue<ll>Q;
rp(i,,)if(tr[].nxt[i])Q.push(tr[].nxt[i]);
while(!Q.empty())
{
ll nw=Q.front();Q.pop();
rp(i,,)
{
if(tr[nw].nxt[i])tr[tr[nw].nxt[i]].fail=tr[tr[nw].fail].nxt[i],Q.push(tr[nw].nxt[i]);
else tr[nw].nxt[i]=tr[tr[nw].fail].nxt[i];
}
}
}
inline void zdj()
{
string str;cin>>str;ll lth=str.length()-,nw=;
rp(i,,lth)
{
nw=tr[nw].nxt[str[i]-'a'+];
for(register ll j=nw;j;j=tr[j].fail)++ass[tr[j].ed].as;
}
} int main()
{
while(gdgs)
{
n=read();if(!n)exit();tr[].clr();cnt=;rp(i,,n)bd(i);fl();tr[].fail=;zdj();
sort(ass+,ass+n+,cmp);printf("%d\n",ass[].as);
cout<<str[ass[].pos]<<endl;rp(i,,n)if(ass[i].as==ass[i-].as)cout<<str[ass[i].pos]<<endl;else break;
}
return ;
}

,,,玄学事件?我开始打的是for(i)里套个for(i)也过去辣QAQ?

然后放下被安利的题目:

病毒

阿狸的打字机

单词

最短母串问题

阿最后说一下,还有一个小优化叫$last$优化,就将$fail$再优化了下,复杂度是没变的但实际上常有奇效$QwQ$

AC自动机板子题/AC自动机学习笔记!的更多相关文章

  1. Keywords Search HDU - 2222 AC自动机板子题

    In the modern time, Search engine came into the life of everybody like Google, Baidu, etc. Wiskey al ...

  2. AC 自动机刷题记录

    目录 简介 第一题 第二题 第三题 第四题 第五题 第六题 简介 这就是用来记录我对于<信息学奥赛一本通 · 提高篇>一书中的习题的刷题记录以及学习笔记. 一般分专题来写(全部写一起可能要 ...

  3. hdu 2222(AC自动机模版题)

    Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...

  4. PSAPI和ToolHelpAPI学习笔记

    标 题: PSAPI学习笔记 作 者:北极星2003 时 间:2005-07-24 18:36 链 接:http://bbs.pediy.com/showthread.php?threadid=154 ...

  5. AC自动机学习笔记-2(Trie图&&last优化)

    我是连月更都做不到的蒟蒻博主QwQ 考虑到我太菜了,考完noip就要退役了,所以我决定还是把博客的倒数第二篇博客给写了,也算是填了一个坑吧.(最后一篇?当然是悲怆のnoip退役记啦QAQ) 所以我们今 ...

  6. AC 自动机学习笔记

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

  7. 学习笔记:AC自动机

    话说AC自动机有什么用......我想要自动AC机 AC自动机简介:  首先简要介绍一下AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配 ...

  8. HDU 2222 AC自动机模板题

    题目: http://acm.hdu.edu.cn/showproblem.php?pid=2222 AC自动机模板题 我现在对AC自动机的理解还一般,就贴一下我参考学习的两篇博客的链接: http: ...

  9. HDU 3065 (AC自动机模板题)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3065 题目大意:多个模式串,范围是大写字母.匹配串的字符范围是(0~127).问匹配串中含有哪几种模 ...

随机推荐

  1. CentOS开关机命令

    命令简介 shutdown,poweroff,reboot,halt,init都可以进行关机,大致用法. /sbin/halt     [-n] [-w] [-d] [-f] [-i] [-p] [- ...

  2. wd mycloud nas新玩法

    最近家里的小米路由器坏了,主要是硬盘读取不出,小米之家也无能为力,本想继续在小米之家买个小米路由器,后来了解到了nas,于是想折腾下.我的nas型号是wd mycloud,3TB内置硬盘.功能:可以组 ...

  3. 【Java面试题】13 Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)?

    1.什么是匿名内部类? 内部类,存在于另一个类内部的类,而匿名内部类,顾名思义,就是没有名字的内部类. 2.为什么需要匿名内部类? 每个inner class都能够各自继承某一实现类(implemen ...

  4. Linux下密码抓取神器mimipenguin

    前有Mimikatz,今有mimipenguin,近日国外安全研究员huntergregal发布了工具mimipenguin,一款Linux下的密码抓取神器,可以说弥补了Linux下密码抓取的空缺. ...

  5. MySQL Server 5.7.13

    如何安装MySQL,MySQL两种安装方式_百度经验 http://jingyan.baidu.com/article/cd4c2979033a17756f6e6047.html "C:\P ...

  6. Sublime Text2安装Package Control

    一.安装Package Control 使用Sublime Text2首先就要安装Package Control,这样就能使用丰富的插件包了 安装方法有2种: (1)访问Package Control ...

  7. [mysql] Install/Remove of the Service Denied

    在windos 的cmd下安装mysql 在mysql的bin目录下面执行: mysqld --install 报错: 信息如下: Install/Remove of the Service Deni ...

  8. Java 基本语法----进制、运算符

    进 制 对于整数,有四种表示方式: 二进制:0,1 ,满 2 进 1.以 0b 或 0B 开头.十进制:0-9 ,满 10 进 1. 八进制:0-7 ,满 8 进1. 以数字 0 开头表示.十六进制: ...

  9. Mac下,如何把Github上的仓库删除掉

    这个虽然简单,但是还是做个记录,当初也是找不到地方,最终还是去百度了,步骤很简单: 如下: 1.进入Github主页,选中你要删除的仓库,点击进入到如下页面:

  10. linux大全链接

    http://man.linuxde.net/