hdoj5769后缀自动机版本
网上的题解都是后缀数组,我来个后缀自动机题解。
建好后缀自动机后由于后缀自动机是单向的,那么dfs一遍记录各节点的size,要保证一个节点只经过一次才是O(n),否则是O(n^2)。表示这个节点及后面还有几个节点。然后再来个ans数组,再dfs一次。这次如果走的是题目要的字母(记c),那么ans[x]+=siz[to],因为to能到的节点对应的子串都有c。如果走的不是c,那么ans[x]+=ans[to]。ans其实就表示该节点以后能有几个能有c的子串。同样ans只能走一次,否则是n^2的。那么开始时memset为-1。走到一个节点就赋为0。这样-1的点就是还需要dfs的,一个点只走一次。具体看两个dfs函数。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <iomanip>
#include <cstring>
#include <map>
#include <queue>
#include <set>
#include <cassert>
#include <stack>
#include <bitset>
#define mkp make_pair
using namespace std;
const double EPS=1e-;
typedef long long lon;
const lon SZ=,SSZ=*SZ,APB=,INF=0x7FFFFFFF,mod=;
lon cnt,maxlen[SSZ],minlen[SSZ],nex[SSZ][APB];
lon slink[SSZ],siz[SSZ],ans[SSZ];
char dst,ch[SZ]; lon add(lon pre,lon c)
{
lon z=++cnt;
maxlen[z]=maxlen[pre]+;
lon u=pre;
for(;u!=-&&!nex[u][c];u=slink[u])
{
nex[u][c]=z;
}
if(u==-)
{
slink[z]=;
minlen[z]=;
}
else
{
lon x=nex[u][c];
if(maxlen[x]==maxlen[u]+)
{
slink[z]=x;
minlen[z]=maxlen[slink[z]]+;
}
else
{
lon v=++cnt;
memcpy(nex[v],nex[x],sizeof(nex[x]));
slink[v]=slink[x];
maxlen[v]=maxlen[u]+;
minlen[v]=maxlen[slink[v]]+;
slink[x]=slink[z]=v;
minlen[x]=maxlen[slink[x]]+;
minlen[z]=maxlen[slink[z]]+;
for(;u!=-&&nex[u][c]==x;u=slink[u])
{
nex[u][c]=v;
}
}
}
return z;
} void init()
{
scanf(" %c",&dst);
scanf(" %s",ch+);
lon pre=;
slink[]=-;
cnt=;
memset(ans,-,sizeof(ans));
for(lon i=;ch[i];++i)
{
pre=add(pre,ch[i]-'a');
}
} void dfs1(lon x)
{
siz[x]=;
for(lon i=;i<APB;++i)
{
lon t=nex[x][i];
if(t)
{
if(!siz[t])dfs1(t);
siz[x]+=siz[t];
}
}
} void dfs2(lon x)
{
ans[x]=;
for(lon i=;i<APB;++i)
{
lon t=nex[x][i];
if(t)
{
if(ans[t]==-)dfs2(t);
if(i==dst-'a')ans[x]+=siz[t];
else ans[x]+=ans[t];
}
}
} void work()
{
dfs1();
dfs2();
cout<<ans[]<<endl;
for(int i=;i<=cnt;++i)
{
memset(nex[i],,sizeof(nex[i]));
siz[i]=;
}
} int main()
{
//std::ios::sync_with_stdio(0);
//freopen("d:\\1.txt","r",stdin);
lon casenum;
cin>>casenum;
//cout<<casenum<<endl;
for(lon time=;time<=casenum;++time)
//for(lon time=1;cin>>n>>len>>wid;++time)
{
cout<<"Case #"<<time<<": ";
init();
work();
}
return ;
}
hdoj5769后缀自动机版本的更多相关文章
- 后缀自动机(SAM)学习笔记
目录 定义 SAM 的状态集 一些性质 SAM 的后缀链接 SAM 的转移函数 一些性质 算法构造 构造方法 时间复杂度证明 状态的数量 转移的数量 代码实现 实际应用 统计本质不同的子串个数 计算任 ...
- SPOJ8093Sevenk Love Oimaster(广义后缀自动机)
Oimaster and sevenk love each other. But recently,sevenk heard that a girl named ChuYuXun was da ...
- 后缀自动机SAM BZOJ 2806
终于遇到了一道后缀数组不能过 一定要学SAM的题... (看了半个下午+半个上午) 现在总结一下(是给我自己总结..所以只总结了我觉得重要的 .. 看不太懂的话可以To http://blog.c ...
- CF547E Milk and Friends(AC自动机的fail指针上建主席树 或 广义后缀自动机的parent线段树合并)
What-The-Fatherland is a strange country! All phone numbers there are strings consisting of lowercas ...
- 【洛谷4482】Border的四种求法(后缀自动机_线段树合并_链分治)
这题我写了一天后交了一发就过了我好兴奋啊啊啊啊啊啊 题目 洛谷 4482 分析 这题明明可以在线做的,为什么我见到的所有题解都是离线啊 -- 什么时候有机会出一个在线版本坑人. 题目的要求可以转化为求 ...
- 一文读懂后缀自动机 Suffix_Automata
原论文(俄文)地址:suffix_automata 原翻译(中文)地址:后缀自动机详解(DZYO的博客) Upd:强推浅显易懂(?)的SAM讲解 后缀自动机 后缀自动机(单词的有向无环图)--是一种强 ...
- 『后缀自动机入门 SuffixAutomaton』
本文的图片材料多数来自\(\mathrm{hihocoder}\)中详尽的\(SAM\)介绍,文字总结为原创内容. 确定性有限状态自动机 DFA 首先我们要定义确定性有限状态自动机\(\mathrm{ ...
- 后缀自动机(SAM)奶妈式教程
后缀自动机(SAM) 为了方便,我们做出如下约定: "后缀自动机" (Suffix Automaton) 在后文中简称为 SAM . 记 \(|S|\) 为字符串 \(S\) 的长 ...
- BZOJ 后缀自动机四·重复旋律7
后缀自动机四·重复旋律7 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一段音乐旋律可以被表示为一段数构成的数列. 神奇的 ...
随机推荐
- ADB命令(全)
当熟悉Shell命令的人使用adb是没有任何难度的,因为adb中绝大多少命令都是引用的shell命令 以下命令进行归类,红色部分字体是测试人员常用的adb命令 基础命令 1.启动adb服务 adb s ...
- MAC OSX Xcode硬盘清理
1.移除对旧设备的支持影响:可重新生成:再连接旧设备调试时,会重新自动生成.我移除了4.3.2, 5.0, 5.1等版本的设备支持.路径:~/Library/Developer/Xcode/iOS D ...
- 2、Flutter 填坑记录篇
1.前言 之前写了一篇文章关于 flutter 初体验的一篇,https://www.cnblogs.com/niceyoo/p/9240359.html,当时一顿骚操作,然后程序就跑起来了. 隔了好 ...
- JQuery插件之【jqGrid】常用语法整理
jqGrid常用语法整理,包含数据获取.常用函数.触发事件等 jqGrid表格数据获取相关语法 获取表格所有数据 $("#grid").jqGrid("getRowDat ...
- 构造方法 this super
1 构造方法 1.1 构造方法Constructor概述创建对象要明确属性值,此时需要用到构造方法,即对象创建时要执行的方法,用来给对象的属性进行初始化.在new对象时,知道其执行的构造方法是什么,就 ...
- 希尔排序(Python实现)
目录 1.for版本--希尔排序 2. while版本--希尔排序 3. 测试用例 4. 算法时间复杂度分析 1.for版本--希尔排序 def shell_sort_for(a_list): ''' ...
- JAVA微信支付代码(WeChatPay.java 才是调用类)
微信官方文档:https://pay.weixin.qq.com/wiki/doc/api/index.html MD5Util.java package weixin; import java.se ...
- 下载工具axel 和 mwget
axel, yum安装或者apt-get安装 但有时axel不行,需要上wget,但单线程的太慢,需要安装mwget.apt-get -y install intltoolwget http://ja ...
- Kaggle比赛:从何着手?
介绍 参加Kaggle比赛,我必须有哪些技能呢? 你有没有面对过这样的问题?最少在我大二的时候,我有过.过去我仅仅想象Kaggle比赛的困难度,我就感觉害怕.这种恐惧跟我怕水的感觉相似.怕水,让我无法 ...
- 《linux就该这么学》第十节课:第8章iptables和firewalld
网卡配置: 物理机:192.168.10.1/24 服务器:192.168.10.10/24 客户端:192.168.10.20/24 1.vim /etc/sysc ...