SPOJ NSUBSTR Substrings
题意
给出一个字符串S,令\({F(x)}\)表示S的所有长度为x的子串出现次数的最大值。求\({F(1)......F(length(S))}\)
MashiroSky的题解
另外我觉得他的总结写得也不错。
后缀自动机例题,下面写几点自己认为理解后缀自动机的重点。
- 后缀自动机相对于后缀树就是将Right集合相同的子串合用一个节点来表示。每一个节点代表一个状态S,这个状态可能包含很多长度区间连续的子串,这些子串的右端点固定,它们的Right集合相同。
- 往上跳parent的过程相当于将子串的前面一节截掉,得到一个长度更短的子串,它们的Right集合变多了。走状态转移边的过程相当于在子串的后面添加新的字符,到达新的状态。
- 构造过程中,情况一很好理解,考虑情况二和情况三的区别。情况二是parent中存在x边到达某一个状态\({V_q}\),并且这个状态的所有子串都可以接受当前插入的这个这个后缀。情况三是虽然存在状态\({V_q}\),但是这个状态所包含一部分长度比较长的的子串无法接受要插入的这个后缀,所以将它拆成两份,一份可以接受,一份不能接受。
对于这道题,我们需要做的就是计算SAM中每个节点的Right集合的大小,即在串中的出现次数。因为parent树的某个节点Right集合是它父亲的真子集,所以我们考虑从parent树的底端向上不断更新祖先的Right集合。因为len更大的节点在parent树上肯定深度更深,所以用基数排序确定拓扑序,然后更新。由于是树形结构,所以不会重复计算。
时间复杂度\(O(|S|)\)
代码
随便取个名字都重名了。
co int N=2.5e5+2;
char s[N];
int n,root,last,sz;
int ch[N*2][26],len[N*2],link[N*2];
void extend(int c){
int np=++sz,p=last;last=np;
len[np]=len[p]+1;
for(;p&&!ch[p][c];p=link[p]) ch[p][c]=np;
if(!p) link[np]=root;
else{
int q=ch[p][c];
if(len[q]==len[p]+1) link[np]=q;
else{
int nq=++sz;len[nq]=len[p]+1;
memcpy(ch[nq],ch[q],sizeof ch[q]);
link[nq]=link[q],link[np]=link[q]=nq;
for(;p&&ch[p][c]==q;p=link[p]) ch[p][c]=nq;
}
}
}
int b[N],ref[N*2],right[N*2],f[N];
int main(){
// insert
scanf("%s",s+1),n=strlen(s+1);
root=last=sz=1;
for(int i=1;i<=n;++i) extend(s[i]-'a');
// topu-sort
for(int p=root,i=1;i<=n;++i) p=ch[p][s[i]-'a'],::right[p]=1;
for(int i=1;i<=sz;++i) ++b[len[i]];
for(int i=1;i<=n;++i) b[i]+=b[i-1];
for(int i=1;i<=sz;++i) ::ref[b[len[i]]--]=i;
for(int i=sz;i>=1;--i) ::right[link[::ref[i]]]+=::right[::ref[i]];
// solve
for(int i=1;i<=sz;++i) f[len[i]]=max(f[len[i]],::right[i]);
for(int i=n;i>=1;--i) f[i]=max(f[i],f[i+1]);
for(int i=1;i<=n;++i) printf("%d\n",f[i]);
return 0;
}
SPOJ NSUBSTR Substrings的更多相关文章
- SPOJ NSUBSTR Substrings 后缀自动机
人生第一道后缀自动机,总是值得纪念的嘛.. 后缀自动机学了很久很久,先是看CJL的论文,看懂了很多概念,关于right集,关于pre,关于自动机的术语,关于为什么它是线性的结点,线性的连边.许多铺垫的 ...
- SPOJ NSUBSTR Substrings ——后缀自动机
建后缀自动机 然后统计次数,只需要算出right集合的大小即可, 然后更新f[l[i]]和rit[i]取个max 然后根据rit集合短的一定包含长的的性质,从后往前更新一遍即可 #include &l ...
- spoj NSUBSTR - Substrings【SAM】
先求个SAM,然后再每个后缀的对应点上标记si[nw]=1,造好SAM之后用吧parent树建出来把si传上去,然后用si[u]更新f[max(u)],最后用j>i的[j]更新f[i] 因为每个 ...
- spoj 8222 Substrings (后缀自动机)
spoj 8222 Substrings 题意:给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值.求F(1)..F(Length(S)) 解题思路:我们构造S的SAM,那么对于 ...
- 【SPOJ】Substrings(后缀自动机)
[SPOJ]Substrings(后缀自动机) 题面 Vjudge 题意:给定一个长度为\(len\)的串,求出长度为1~len的子串中,出现最多的出现了多少次 题解 出现次数很好处理,就是\(rig ...
- SPOJ - NSUBSTR 后缀自动机板子
SPOJ - NSUBSTR #include<bits/stdc++.h> #define LL long long #define fi first #define se second ...
- SPOJ NSUBSTR (后缀自动机)
SPOJ NSUBSTR Problem : 给一个长度为n的字符串,要求分别输出长度为1~n的子串的最多出现次数. Solution :首先对字符串建立后缀自动机,在根据fail指针建立出后缀树,对 ...
- ●SPOJ 8222 NSUBSTR–Substrings
题链: http://www.spoj.com/problems/NSUBSTR/题解: 后缀自动机. 不难发现,对于自动机里面的一个状态s, 如果其允许的最大长度为maxs[s],其right集合的 ...
- ●SPOJ 8222 NSUBSTR - Substrings(后缀数组)
题链: http://www.spoj.com/problems/NSUBSTR/ 题解: 同届红太阳 --WSY给出的后缀数组解法!!! 首先用倍增算法求出 sa[i],rak[i],hei[i]然 ...
随机推荐
- 执行这些代码, Edit1只能输入数字,小数点和负号,负号和小数点只能输入一个,负号必须在最前,粘贴的数字必须完全正确.
执行这些代码, Edit1只能输入数字,小数点和负号,负号和小数点只能输入一个,负号必须在最前,粘贴的数字必须完全正确. type TForm1 = class(TForm) Edit1: TEdit ...
- 当你有双网络(内部网+互联网)时,如何透明NAT给其他电脑上网。虚拟机+爱快
一:简介 具体环境是这样的:单位没有提供互联网连接,都是内部网,linux服务器,无法连接源更新,docker无法pull镜像,python无法在线pip安装包. 真是郁闷到想死啊. 好在我的笔记本有 ...
- Java数值类型之间转换
Java之间的数值转换如图所示,实心箭头代表无数据丢失,虚线箭头代表可能丢失 例如:123456789是一个大的整数,包含的位数比float类型能够表达的位数多,但这个数转换为float类型时,将会得 ...
- Ubuntu16.04 安装Teamviewer
有时需要远程控制ubuntu系统的电脑,Teamviewer在linux下也可以进行安装,大致看了下向日葵在linux下配置好像比较麻烦,而且Teamviewer远程控制的流畅性一直不错,就选择安装T ...
- Docker(3):Dockerfile介绍及简单示例
Dockerfile 概念 Dockerfile是由一系列命令和参数构成的脚本,这些命令应用于基础镜像并最终创建一个新的镜像.它们简化了从头到尾的流程并极大的简化了部署工作.Dockerfile从FR ...
- 20165326 java第七周学习笔记
第七周学习笔记 MySQL(数据管理系统)学习 知识点总结: 不能通过关闭MySQL数据库服务器所占用的命令行窗口来关闭MySQL数据库. 如果MySQL服务器和MySQL管理工具驻留在同一台计算机上 ...
- oracle概要文件profile详解
一.目的: Oracle系统中的profile可以用来对用户所能使用的数据库资源进行限制,使用Create Profile命令创建一个Profile,用它来实现对数据库资源的限制使用,如果把该prof ...
- 创建vue项目
1.创建项目 vue creat 项目名 // 要提前进入目标目录(项目应该创建在哪个目录下) // 选择自定义方式创建项目,选取Router, Vuex插件 2.启动/停止项目 npm run se ...
- drf 分页
分页: 1.简单的分页: 每页显示条数: page_size = api_settings.PAGE_SIZE 查询的页码数: page_query_param = "page" ...
- 2019-03-21-day016-正则表达式
昨日内容回顾 基本数据类型 编码 流程控制 文件操作 函数-内置函数 装饰器 常用模块: 序列化模块 随机数模块 os模块 sys模块 时间模块 hashlib collections re 1天半 ...