初学AC自动机,要先对于每一个模式串求出来trie树,在此基础上构建fail指针,然后在trie树加上失配边构建出整张trie图。

AC自动机的原理和KMP差不多,一个节点的fail指针就是指向trie树上一个最长前缀等于这个单词的后缀。

首先fail[0]=0,然后把0有的每个孩子push进一个队列里(如果直接push(0)的话会出现f[x]=x),然后bfs。

设一个节点为u,父亲为v,那么如果ch[fail[v]][u是v的哪个孩子]!=0,那么fail[u]就等于它,否则就不停的跳fail直到0或存在这个孩子。

但我们可以用trie图来优化这个过程,每个节点的每个孩子都不为空,如果原本为空就直接指向上一步用while循环求的那个孩子(具体看代码),于是跳的时候无脑跳一步就行了。

考虑这道题,一个单词一定为trie上的一个节点,而且它出现在文章中一定是一个前缀的后缀,所以那些fail指针直接或间接指向它的节点一定包含这个前缀,所以用bfs序倒着dp一遍就行了。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define N 1000005
using namespace std;
int n;
char s[N];
int cnt;
int ch[N][],f[N],ans[N],sum[N];
int b[N];
void in(int xx)
{
int now=,l=strlen(s);
for(int i=;i<l;i++)
{
int x=s[i]-'a';
if(!ch[now][x])ch[now][x]=++cnt;
now=ch[now][x];sum[now]++;
}
b[xx]=now;
}
queue<int>q;int a[N];int tot;
void fail()
{
f[]=;
for(int i=;i<;i++)
{
int u=ch[][i];
if(u)q.push(u),a[++tot]=u;
}
while(!q.empty())
{
int tmp=q.front();q.pop();a[++tot]=tmp;
for(int i=;i<;i++)
{
int u=ch[tmp][i];
if(!u)
{
ch[tmp][i]=ch[f[tmp]][i];continue;
}
q.push(u);f[u]=ch[f[tmp]][i];
}
}
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%s",s);
in(i);
}
fail();
for(int i=tot;i>=;i--)sum[f[a[i]]]+=sum[a[i]];
for(int i=;i<=n;i++)
{
printf("%d\n",sum[b[i]]);
}
return ;
}

bzoj 3172 AC自动机的更多相关文章

  1. 【无聊放个模板系列】BZOJ 3172 (AC自动机)

    #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #inc ...

  2. bzoj 2434 AC自动机+树状数组

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 3493  Solved: 1909[Submit][Sta ...

  3. bzoj 1030 AC自动机+dp

    代码: //先把给的单词建AC自动机并且转移fail,然后d[i][j]表示构造的文章到第i位时处在字典树的第j个节点的不包含单词的数量,最后用总的数量26^m //-d[m][0~sz]即可.其中不 ...

  4. bzoj 2434 ac自动机

    ac自动机中,如果以trie中的节点为节点,(fail[i],i)为边,可以建立一颗树,该树有如下特点:“节点u是节点v的祖先 当且仅当 u代表的字符串是v代表的字符串的一个后缀”.(u代表的字符串是 ...

  5. bzoj 2754 ac自动机

    第一道AC自动机题目. 记一下对AC自动机的理解吧: AC自动机=Trie+KMP.即在Trie上应用KMP思想,实现多Pattern的匹配问题. 复杂度是预处理O(segma len(P)),匹配是 ...

  6. bzoj 1030 ac自动机

    比较容易看出来先建立ac自动机,然后在自动机上做DP,设w[0..1][i][j]为当前不包括/包括字典中的字符串,当前在自动机中走到第i个节点,完成的文本的长度为j的方案数,那么比较容易的转移w[i ...

  7. bzoj 2434 AC自动机 + fail指针建树 + 树状数组

    思路:我们先跟着它给定的字符串走把字典树建出来,求出fail指针,我们考虑两个字符串 A和B, 如果想要求B中有多少A的子串,转换一下就是有多少个B的前缀的后缀包含A,这个在AC自动机 的状态图中很容 ...

  8. bzoj 1444 AC自动机 + 矩阵乘法 | 高斯消元

    恶补了一下AC自动机,花了一天时间终于全部搞明白了. 思路:将每个人的串加入AC自动机,在AC自动机生成的状态图上建边,注意单词末尾的节点只能转移到自己概率为1, 然后将矩阵自乘几十次后误差就很小了, ...

  9. BZOJ 3940 AC自动机

    思路: 需要维护一个栈的AC自动机--. 要求出来 最后的栈顶是在自动机上的哪个节点. if(!ac.ch[st[tp-1]][a[i]-'a']) st[tp]=ac.ch[ac.f[st[tp-1 ...

随机推荐

  1. Centos5.8 安装SVN并配置HTTP访问

    安装 svn sudo yum install subversion 测试 svn --version 安装 httpd 的 svn 模块 sudo yum install mod_dav_svn 前 ...

  2. java中wait/notify机制

    通常,多线程之间需要协调工作.例如,浏览器的一个显示图片的线程displayThread想要执行显示图片的任务,必须等待下载线程 downloadThread将该图片下载完毕.如果图片还没有下载完,d ...

  3. NOI2018准备Day5

    3个半小时,连看题解带超过了一道二分题.

  4. python install

    Install all dependencies by pip install -r requirements.txt (Run this command from project root)

  5. 【自己给自己题目做】:如何在Canvas上实现魔方效果

    最终demo -> 3d魔方 体验方法: 浮动鼠标找到合适的位置,按空格键暂停 选择要翻转的3*3模块,找到相邻两个正方体,鼠标点击第一个正方体,并且一直保持鼠标按下的状态直到移到第二个正方体后 ...

  6. [云上天气预报-有时有闪电]2月3日23:00-4:00阿里云SLB升级期间网络会闪断

    大家好,2月3日23:00-2月4日4:00,阿里云将对SLB(负载均衡)进行升级,在升级期间,SLB会有约4-8次的网络闪断.由此给您带来麻烦,望谅解! 阿里云官方公告内容如下: 尊敬的用户: 您好 ...

  7. Linux sysinfo获取系统相关信息

    Linux中,可以用sysinfo来获取系统相关信息. #include <stdio.h> #include <stdlib.h> #include <errno.h& ...

  8. Tensorflow学习笔记2:About Session, Graph, Operation and Tensor

    简介 上一篇笔记:Tensorflow学习笔记1:Get Started 我们谈到Tensorflow是基于图(Graph)的计算系统.而图的节点则是由操作(Operation)来构成的,而图的各个节 ...

  9. DNS资源纪录(Resource Record)介绍

          http://dns-learning.twnic.net.tw/bind/intro6.html 类型 SOA NS A AAAA PTR CNAME MX -------------- ...

  10. DeviceFamily XAML Views(一)

    DeviceFamily Veiws 可以为特定的设备(Mobile.Desktop等)制作特定的XAML视图,这种方式可以完全定制XMAL和共享后台代码. 以 Mobile 和 Desktop 为例 ...