后缀自动机Suffix Links的应用

 

前置:

题目&讲解:http://hihocoder.com/problemset/problem/1449

 

问题一:如何求出Suffix Links每个节点的endpos()大小

先拉出3条性质,这两条性质在先前blog都有提及

  1. 对于所有同一个节点的子串,一定满足集合endpos()相同,除此之外,endpos()相同的所有子串一定属于同一个节点,并且这些字符串是一段连续的后缀
  2. 所有的Suffix Links构成了一颗根节点为0的内向树,如果u的v的父亲,那么满足v一定是u的子集(默认指节点的endpos)
  3. s1是s2的后缀当且仅当endpos(s2) ⊆ endpos(s1),s1不是s2的后缀当且仅当endpos(s1) ∩ endpos(s2) = ∅

有些东西是求不出来的,例如你无法求出所有节点的endpos集合所有元素,因为元素个数是O(len²)的,除此之外,|endpos()|不能动态更新,因为每插入一个字符,最坏情况下所有的节点的endpos都会被改变,例如全a字符串

→所以你只能在字符串插入结束后,静态求出所有节点的|endpos()|,也就是每个节点endpos()元素个数

那么每个节点的|endpos()|怎么求

一些推导性质:

  1. 由上面性质③可得:如果u是v的父亲,那么一定满足endpos(v) ⊂ endpos(u),除此之外如果两个节点u, v不满足其中一个是另一个的祖先,那么endpos(u) ∩ endpos(v) = ∅
  2. 由上可得:对于节点u,如果节点u不包含子串S[1..i],也就是不存在母串的某个前缀,那么满足|endpos(u)| = ∑|endpos(son(u))|,其中son(u)为u点的所有儿子,否则|endpos(u)| = ∑|endpos(son(u))|+1

由推导性质,就可以轻松在线性时间内求出所有节点的|endpos()|了

 

 

问题二:给你长度为n的母串,对于每一个的k∈[1, n],求出所有长度为k的子串中出现次数最多的子串出现次数

很显然先要求出所有节点的|endpos()|

如果|endpos(u)| = 15,这就说明节点u所有的子串都出现了刚好15次,这样的话,假设|endpos(u)| = 15,len(u) = 18,这就说明所有长度≤18的子串中出现次数最多的子串出现次数一定≥18

步骤如下:

  1. 求出SAM,并建出Suffix Links
  2. 对Suffix Links进行DFS时求出所有节点的|endpos()|
  3. 在如上过程中求出 ans[k] 表示长度≤k的子串中出现次数最多的子串出现次数的最小值
  4. 对ans[]求一遍后缀最大值就是答案

题目&代码:https://blog.csdn.net/Jaihk662/article/details/82830607

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值