BZOJ4502串——AC自动机(fail树)
题目描述
输入
输出
样例输入
ab
ac
样例输出
提示
1<=n<=10000,每个字符串非空且长度不超过30,均为小写字母组成。
因为trie树上每个点到根都是一个前缀,所以假设trie树上有cnt个点,最多就能有cnt^2个“好”字符串,但有些情况是重复的,比如:字符串集合里有aa和ab连个串,那么‘aa’+‘b'和‘a’+‘ab’在本质上是一个串。所以只要把重复的都去掉就是问题的答案了。如下图所示,
绿串和短黑串与红串和长黑串就属于重复的答案,我们取红串和长黑串为记录的答案,就要把绿串的这种情况去掉。可以发现在AC自动机上,红串是绿串的后缀,蓝串是长黑串的后缀,所以对于每个红串与绿串,它们相差的部分(也就是蓝串)是几个串的后缀(就相当于有几个能和红串、绿串匹配的黑串),就要把答案相应的减去多少。在fail树上就转化成了以蓝串的末端点为根的子树中有多少个节点(不算本身,因为本身代表自己是自己的后缀,那么绿串前面的黑串就是空串)。所以对于AC自动机上每个fail指针不为根节点的节点(如果fail指针是根节点它就没有后缀),找它和它fail指针指向的串相差的部分所组成的串,用总答案减掉在fail树上子树大小就是最终结果。
- #include<cmath>
- #include<queue>
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- using namespace std;
- int n;
- int cnt;
- int num;
- char s[40];
- long long ans;
- int f[300010];
- int fail[300010];
- int a[300010][26];
- long long sum[300010];
- void build(char *s)
- {
- int now=0;
- int len=strlen(s);
- for(int i=0;i<len;i++)
- {
- if(!a[now][s[i]-'a'])
- {
- a[now][s[i]-'a']=++cnt;
- f[cnt]=now;
- }
- now=a[now][s[i]-'a'];
- }
- }
- void getfail()
- {
- queue<int>q;
- for(int i=0;i<26;i++)
- {
- if(a[0][i])
- {
- fail[a[0][i]]=0;
- q.push(a[0][i]);
- }
- }
- while(!q.empty())
- {
- int now=q.front();
- q.pop();
- for(int i=0;i<26;i++)
- {
- if(a[now][i])
- {
- fail[a[now][i]]=a[fail[now]][i];
- q.push(a[now][i]);
- }
- else
- {
- a[now][i]=a[fail[now]][i];
- }
- }
- }
- return ;
- }
- void solve()
- {
- for(int i=1;i<=cnt;i++)
- {
- for(int j=fail[i];j;j=fail[j])
- {
- sum[j]++;
- }
- }
- for(int i=1;i<=cnt;i++)
- {
- if(fail[i])
- {
- int j=i;
- int k=fail[i];
- while(k)
- {
- j=f[j];
- k=f[k];
- }
- ans-=sum[j];
- }
- }
- }
- int main()
- {
- scanf("%d",&n);
- for(int i=0;i<n;i++)
- {
- scanf("%s",s);
- build(s);
- }
- getfail();
- ans=1ll*cnt*cnt;
- solve();
- printf("%lld",ans);
- return 0;
- }
BZOJ4502串——AC自动机(fail树)的更多相关文章
- BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]
3172: [Tjoi2013]单词 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 3198 Solved: 1532[Submit][Status ...
- 【BZOJ-3881】Divljak AC自动机fail树 + 树链剖分+ 树状数组 + DFS序
3881: [Coci2015]Divljak Time Limit: 20 Sec Memory Limit: 768 MBSubmit: 508 Solved: 158[Submit][Sta ...
- 【BZOJ-2434】阿狸的打字机 AC自动机 + Fail树 + DFS序 + 树状数组
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2022 Solved: 1158[Submit][Sta ...
- AC自动机 & Fail树 专题练习
Fail树就是AC自动机建出来的Fail指针构成的树. [bzoj3172][xsy1713]单词 题意 给定一些单词,求每个单词在所有单词里面的出现次数. 分析 构建Fail树,记录每个单词最后一个 ...
- BZOJ2905: 背单词 AC自动机+fail树+线段树
$zjq$神犇一眼看出$AC$自动机 $Orz$ 直接就讲做法了 首先对每个串建出$AC$自动机 将$fail$树找到 然后求出$dfs$序 我们发现一个单词 $S_i$是$S_j$的子串当且仅当$S ...
- 【学习笔记】ac自动机&fail树
定义 解决文本串和多个模式串匹配的问题: 本质是由多个模式串形成的一个字典树,由tie的意义知道:trie上的每一个节点都是一个模式串的前缀: 在trie上加入fail边,一个节点fail边指向这个节 ...
- 【AC自动机/fail树】BZOJ3172- [Tjoi2013]单词
[题目大意] http://www.lydsy.com:808/JudgeOnline/problem.php?id=3172 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多 ...
- 洛谷2414(构建ac自动机fail树dfs序后遍历Trie树维护bit及询问答案)
要点 这是一道蔡队题,看我标题行事 任意询问y串上有多少个x串,暴力找每个节点是不是结尾肯定是炸的,考虑本质:如果某节点是x的结尾,根据ac自动机的性质,x一定是此(子)串后缀.又有每个Trie节点的 ...
- BZOJ 2905: 背单词 AC自动机+fail树+dfs序+线段树
Description 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使得其中的每个单词是后一个单词的子串,最大化子序列中W的和. Input 第一行一个整数TEST,表示数据组 ...
随机推荐
- Ubuntu下禁止自动打开U盘等设备
打开终端 禁止自动挂载: $ gsettings set org.gnome.desktop.media-handling automount false 禁止自动挂载并打开 $ gsettings ...
- Ubuntu系统多屏幕时 触摸屏如何分屏定位
有很多的使用我们需要在Ubuntu系统中使用多屏幕的情况,但是有的时候是一个屏幕的触摸屏幕,另一个屏幕是非触摸屏幕,但是问题来了, 有的时候在触摸屏幕上点击的时候竟然在非触摸的响应,这种情况非常不友好 ...
- Sublime3 - 插件cssrem
一个CSS的px值转rem值的Sublime Text 3自动完成插件. 插件效果如下: 安装: 1. 现在本地clone一份: git clone https://github.com/hyb628 ...
- http一次请求过程
物理层:支持底层网络协议: 其中网络层支持IP协议: 传输层支持TCP协议,它是面向连接的: 应用层支持 http,ftp tftp,SMTP,DHCP协议 一个完整的http请求过程: 1.浏览器 ...
- Vue-条件渲染v-if与v-show
一.共同点 根据数据值来判断是否显示DOM元素 二.区别 代码: <!DOCTYPE html> <html lang="en"> <head> ...
- Intel x86_64 Architecture Background 3
多层次的cache结构解决了CPU和DRAM之间处理速度不一致的问题,在Intel体系架构下,CPU核心和主存DRAM之间有着三层的cache.其中一层缓存L1和二层缓存L2在CPU核心(core)中 ...
- 5分钟入门自动化测试——你应该学会的Postman用法(2)
前言 之前的一篇文章<你应该学会的Postman用法>,主要介绍了postman的一些高级的用法,便于日常开发和调试使用,本文的基础是对postman的基本使用以及一些高级用法有一定的了解 ...
- 正则&highlight高亮实现(干货)
写完正则表达式以后在浏览器上检测实在是不方便,于是就写了一个JS正则小工具,大大地提高了学习效率.学习之余用正则实现了一个highlight高亮demo,欢迎交流. 什么是正则表达式? 简单的说:正则 ...
- QQ群管理员申请帖(本次截止日期为2017-03-25)
本帖专门为技术交流群申请管理员专用. 管理员的权利: 1.有权在成员违规的情况下直接剔除. 2.有权加入多个交流群. 3.有权引人入群. 4.艾特全体是权利,但要慎用,通常情况下,没有我本人的授意,不 ...
- @Pointcut的用法
在Spring 2.0中,Pointcut的定义包括两个部分:Pointcut表示式(expression)和Pointcut签名(signature).让我们先看看execution表示式的格式: ...