题目链接:点击查看

题目大意:给出n个模式串,问在主串中分别出现了多少次

题目分析:如果像以往那样,在匹配的时候fail指针乱跳的话,那么是错误的AC自动机使用方法,时间复杂度也大大上升,接近于暴力的复杂度,正确的做法是建立一棵fail树,原理就是因为每一个节点的fail指针都是唯一的,并且是指向另外的一个节点,也就是说一个节点可以被多个fail指针所指,那么我们可以将这条边的方向反过来,也就是一个节点可以到达多个fail指针所指的其他节点,这样就形成了一棵fail树,接下来我们就可以在自动机上记录每个模式串在字典树的终止节点上匹配了多少次,最后跑一次简单树形dp就跑出每个点的答案了

在建立字典树的时候记得将每个字符串的编号和终止节点映射一下,方便答案的输出

代码:

#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=2e6+100;char s[N];int trie[N][26],cnt;int rk[N];//rk[序号]=编号:序号与终止节点的映射int fail[N];int dp[N];vector<int>node[N];void insert_word(int x)
{int pos=0;for(int i=0;s[i];i++){int to=s[i]-'a';if(!trie[pos][to])trie[pos][to]=++cnt;pos=trie[pos][to];}rk[x]=pos;
}void getfail()
{queue<int>q;for(int i=0;i<26;i++){int p=trie[0][i];if(p){fail[p]=0;q.push(p);}}while(!q.empty()){int cur=q.front();q.pop();for(int i=0;i<26;i++){int p=trie[cur][i];if(p){fail[p]=trie[fail[cur]][i];q.push(p);}elsetrie[cur][i]=trie[fail[cur]][i];}}
}void search_word()
{int pos=0;for(int i=0;s[i];i++){int to=s[i]-'a';pos=trie[pos][to];dp[pos]++;//记录终止节点在主串的出现次数}
}void dfs(int u)
{for(auto v:node[u]){dfs(v);dp[u]+=dp[v];}
}int main()
{
//  freopen("input.txt","r",stdin);
//  ios::sync_with_stdio(false);int n;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%s",s);insert_word(i);}getfail();for(int i=1;i<=cnt;i++)//建立fail树node[fail[i]].push_back(i);scanf("%s",s);search_word();dfs(0);for(int i=1;i<=n;i++)printf("%d\n",dp[rk[i]]);return 0;
}

洛谷P5357 - 【模板】AC自动机(二次加强版)(AC自动机+fail树)相关推荐

  1. 专题·树链剖分【including 洛谷·【模板】树链剖分

    初见安~~~终于学会了树剖~~~ [兴奋]当初机房的大佬在学树剖的时候我反复强调过:"学树剖没有前途的!!!" 恩.真香. 一.重链与重儿子 所谓树剖--树链剖分,就是赋予一个链的 ...

  2. 洛谷·【模板】点分树 | 震波【including 点分树

    初见安-这里是传送门:洛谷P6329 [模板]点分树 | 震波 一.点分树 其实你会点分治的话,点分树就是把点分治时的重心提出来重新连城一棵树. 比如当前点是u,求出子树v的重心root后将root与 ...

  3. 2019.03.21【ZJOI2007】【BZOJ1095】【洛谷P2056】Hide 捉迷藏(DFS序)(线段树)

    BZOJ传送门 洛谷传送门 解析: 其实就是QTREE4的弱化版,可以直接用QTREE4的解法来做. 但是这道题有优秀的O(nlog⁡n)O(n\log n)O(nlogn)做法. 我们考虑利用DFS ...

  4. 【洛谷3345_BZOJ3924】[ZJOI2015]幻想乡战略游戏(点分树)

    大概有整整一个月没更博客了 -- 4 月为省选爆肝了一个月,最后压线进 B 队,也算给 NOIP2018 翻车到 316 分压线省一这个折磨了五个月的 debuff 画上了一个不算太差的句号.结果省选 ...

  5. 洛谷P1877-[HAOI2012]音量调节(二维01背包)

    题目描述: 一个吉他手准备参加一场演出.他不喜欢在演出时始终使用同一个音量,所以他决定每一首歌之前他都需要改变一次音量.在演出开始之前,他已经做好一个列表,里面写着每首歌开始之前他想要改变的音量是多少 ...

  6. 洛谷.4897.[模板]最小割树(Dinic)

    题目链接 最小割树模板.具体见:https://www.cnblogs.com/SovietPower/p/9734013.html. ISAP不知为啥T成0分了.. Dinic: //1566ms ...

  7. 强连通分量:洛谷P3387 模板:缩点

    传送门 顾名思义,模板awa #include <cstdio> #include <cstring> #include <cmath> #include < ...

  8. 线性筛法 欧拉筛c语言,[洛谷P3383][模板]线性筛素数-欧拉筛法

    Hibernate Hql 总结 1.from子句 Hibernate中最简单的查询语句的形式如下: from eg.Cat该子句简单的返回eg.Cat类的所有实例. 通常我们不需要使用类的全限定名, ...

  9. 【后缀数组】洛谷P3809模板题

    题目背景 这是一道模板题. 题目描述 读入一个长度为 n n n 的由大小写英文字母或数字组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在原串中的位置. ...

最新文章

  1. Java8之lambda表达式的总结
  2. 【数据分析】太秀了!用Excel也能实现和Python数据分析一样的功能!
  3. 川大计算机高考分数,2020年四川大学录取分数是多少 2020年高考多少分可以报考四川大学...
  4. CodeForces - 1017D The Wu
  5. 面向对象程序设计要考虑的7个原则
  6. “云时代架构”经典文章阅读感想八
  7. 算法之路(5)--括号匹配问题(Valid Parentheses)[leetcode]
  8. [ExtJs4.0]数据从excle2003导入到数据库【2-1】
  9. Vue源码解析:Vue实例
  10. mir显示服务器,The Legend Of Mir 服务器程序安装说明(图片)
  11. 7-1 计算平均成绩 (15分)
  12. picPick使用研究
  13. mysql 查询最多的_MySQL中用通用查询日志找出查询次数最多的语句的教程
  14. 迈阿密大学的计算机系咋样,迈阿密大学牛津分校计算机专业如何?过来人告诉你...
  15. 解读 ESP32 API参考-system-App Image Format
  16. linux cadaver 命令,【Linux学习第三篇】[Tab].[Ctrl]-c.[Ctrl]-d
  17. 稀疏自动编码(Sparse Autoencoder)
  18. Arduino驱动LED128X64 - U8g2 自定义中文字库
  19. 目标检测:Corner Net论文阅读
  20. Jsp中有哪些内置对象?作用分别是什么?

热门文章

  1. Spring Cloud是什么
  2. MySQL高级 大批量插入数据
  3. 实现Callable接口通过FutureTask包装器来创建Thread线程
  4. MyBatis 源码解读-environmentsElement()
  5. 配置解决中文乱码的过滤器
  6. MySQL服务器参数介绍
  7. aop实现原理-动态代理CGLib代理
  8. Bootstrap全局css样式_表格
  9. freemodbus源码/获取地址
  10. LInux--进程间通信