题意

给出一个字符串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的更多相关文章

  1. SPOJ NSUBSTR Substrings 后缀自动机

    人生第一道后缀自动机,总是值得纪念的嘛.. 后缀自动机学了很久很久,先是看CJL的论文,看懂了很多概念,关于right集,关于pre,关于自动机的术语,关于为什么它是线性的结点,线性的连边.许多铺垫的 ...

  2. SPOJ NSUBSTR Substrings ——后缀自动机

    建后缀自动机 然后统计次数,只需要算出right集合的大小即可, 然后更新f[l[i]]和rit[i]取个max 然后根据rit集合短的一定包含长的的性质,从后往前更新一遍即可 #include &l ...

  3. spoj NSUBSTR - Substrings【SAM】

    先求个SAM,然后再每个后缀的对应点上标记si[nw]=1,造好SAM之后用吧parent树建出来把si传上去,然后用si[u]更新f[max(u)],最后用j>i的[j]更新f[i] 因为每个 ...

  4. spoj 8222 Substrings (后缀自动机)

    spoj 8222 Substrings 题意:给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值.求F(1)..F(Length(S)) 解题思路:我们构造S的SAM,那么对于 ...

  5. 【SPOJ】Substrings(后缀自动机)

    [SPOJ]Substrings(后缀自动机) 题面 Vjudge 题意:给定一个长度为\(len\)的串,求出长度为1~len的子串中,出现最多的出现了多少次 题解 出现次数很好处理,就是\(rig ...

  6. SPOJ - NSUBSTR 后缀自动机板子

    SPOJ - NSUBSTR #include<bits/stdc++.h> #define LL long long #define fi first #define se second ...

  7. SPOJ NSUBSTR (后缀自动机)

    SPOJ NSUBSTR Problem : 给一个长度为n的字符串,要求分别输出长度为1~n的子串的最多出现次数. Solution :首先对字符串建立后缀自动机,在根据fail指针建立出后缀树,对 ...

  8. ●SPOJ 8222 NSUBSTR–Substrings

    题链: http://www.spoj.com/problems/NSUBSTR/题解: 后缀自动机. 不难发现,对于自动机里面的一个状态s, 如果其允许的最大长度为maxs[s],其right集合的 ...

  9. ●SPOJ 8222 NSUBSTR - Substrings(后缀数组)

    题链: http://www.spoj.com/problems/NSUBSTR/ 题解: 同届红太阳 --WSY给出的后缀数组解法!!! 首先用倍增算法求出 sa[i],rak[i],hei[i]然 ...

随机推荐

  1. day3-PyCharm 断点 调试模式

    上篇学习了Python的工具选择,PyCharm的基本设置,简单的了解了下PyCharm的调试模式,今天主要学习下PyCharm的调式模式,在以后的开发中是一个非常重要的工具. [运行]和[调试]前的 ...

  2. OOP⑷

    1.对象数组: /** *学生类 */ public class Student { // 创建一个对象数组保存3名学生的信息 Student[] stus = new Student[3]; int ...

  3. 3.1 C++继承的概念及语法

    参考:http://www.weixueyuan.net/view/6358.html. 总结: 继承可以理解为一个类从另一个类获取方法(函数)和属性(成员变量)的过程. 被继承的类称为父类或基类,继 ...

  4. 2.11 C++转型构造函数

    参考:http://www.weixueyuan.net/view/6343.html 总结: 带参数的构造函数中有两种比较常见的构造函数:拷贝构造函数和转型构造函数. 转型构造函数只有一个参数,如果 ...

  5. html随笔CSS(*^__^*)

    控制文本显示字数,超过规定的文本长度  x显示... white-space:nowrap;        //规定不能换行 overflow:hidden; text-overflow:ellips ...

  6. Oracle远程登录命令

    sqlplus登陆方式 sqlplus有几种登陆方式 比如: 1.C: > sqlplus "/as sysdba" C: > sqlplus / as sysdba ...

  7. 10.Python-第三方库requests详解(二)

    Requests 是用Python语言编写,基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库.它比 urllib 更加方便,可以节约我们大量的工作,完全满足 HTT ...

  8. 20165326 java实验一

    <Java程序设计>Java开发环境的熟悉 实验报告 课程:Java程序设计 班级:1653班 姓名:陈卓 学号:20165326 指导教师:娄嘉鹏 实验日期:2018年4月2日 实验时间 ...

  9. ios初识UITableView及简单用法一

    // // ViewController.m // ZQRTableViewTest // // Created by zzqqrr on 17/8/24. // Copyright (c) 2017 ...

  10. xargs用法

    xargs是一个很有用的命令,它可以实现并行,同&有异曲同工之妙,在大批量管理服务器时非常有用 xargs命令是给其他命令传递参数的一个过滤器,也是组合多个命令的一个工具.它擅长将标准输入数据 ...