标签:树分治 size 一段 log 随机 mes 循环 深度 扫描线
写在前面:今天下午药丸……不会字符串,全程掉线/ll
取反建个SAM,每次二分答案。如果存在,合法串的右端点一定在\([a+len-1,b]\),建个主席树维护一下这些后缀在不在对应串的子树里就可以。
Sol1:
发现我们要维护的就是kmp的\(next\)数组,然而kmp复杂度是均摊的,如果可持久化的话,对某个多次跳\(next\)的位置多次询问就会gg。
我们可以考虑给它严格化一下。
设\(trans_{x,c}\)表示从\(x\)后面添加一个字符\(c\),会转移到的位置。
考虑\(trans_{x,c}\)和\(trans_{next_{x},c}\)有什么不同。
如果\(next_{x}\)后面的字符不是\(c\),显然它们相等。否则\(trans_{x,c}=next_x+1\)。
对\(trans\)数组可持久化一下,每次修改一个位置即可。
Sol2:
每次跳\(next\)的时候,如果\(next_x \leq \frac{x}{2}\),就可以直接跳,因为最多跳\(\log\)次。
否则就说明\(x\)有一个长度为\(x-next_x\)的周期,在周期内不管怎么跳,后一个字符都是相等的。
那么可以直接跳到\(x~ mod~(x-next_x)\)的位置,发现最多也会跳\(\log\)次。
这样复杂度就是严格的了。
首先二分答案,然后考虑倒序处理。每次在前面加入一个字符,用SA判断新增的子串是否超过二分值即可。
发现\(T_x\)一定是\(S\)的子串,否则就可以把它丢掉。
对于每个\(T_x\)可以维护它在\(S\)的SAM上的节点位置,操作1和2可以直接做,操作3可以离线线段树合并或者主席树。
离线扫描线。考虑每次加入新字符的时候怎么办。
先考虑暴力,假设我们在SAM里新加入了这个字符,那它新产生的子串一定是从这个新加入的节点一直跳\(fa\)跳到根,路上经过的节点。
每个节点维护一个\(lstpos\),表示最后一次跳到这个节点的位置,那么左端点在这个位置右边的询问会产生影响。
发现这个操作很像lct的\(access\)操作,所以相同的\(lstpos\)可以看作一段,均摊是\(\log\)段。每段产生的影响会形如一个分段函数,只有常数段,线段树维护即可。
总复杂度\(O(n\log^2 n)\)。
掉线了,咕咕咕。
显然每个\(S_i\)都是\(S_1\)的子串。
一定存在一组最优解,使得对于\(i \geq 2\),任何\(S_{i+1}\)都是\(S_i\)的后缀。
证明比较显然,如果不是后缀,把后缀后面的部分去掉不会影响答案。
所以答案是SAM上的一条链,对每个点二分一下祖先就可以。
最长回文LCP,实际上就是回文树上两两之间的LCA深度。
新加入字母时,考虑它和之前所有节点的LCA深度和,发现每个祖先贡献为\(size_x\times(dep_x-dep_{fa_x})\),是个经典数据结构,LCT维护即可。
这东西的意义其实就是后缀树上两个点之间路径的长度。
树分治找长度不超过\(L\)的路径总数即可。
对后缀树上的每个节点启发式合并子树也可以。
很多LCP类问题用树型结构去分析都有很好的效果。
转化为求最短循环节。发现一段区间的循环节等价于找一个\(x\),使\(x+LCP(L,L+x-1)-1\geq R\)。
从左往右跑扫描线,遇到询问的左端点就加进去。对于每个询问第一次遇到符合条件的\(i\)就可以得到答案。
LCP等于后缀树上的LCA深度。
LCA有两种情况:①\(dep_L>dep_i\),②\(dep_L\leq dep_i\)
可以从后缀树上\(i\)对应的节点往上跳,跳到一个节点的时候,需要对它的子树和祖先(对应两种情况)分别判断是否有询问满足条件,只要维护询问的最小值即可,对于满足条件的可以直接暴力删去。
可以用树剖加速这个过程,复杂度\(O(n\log^2n)\)。
少女掉线中……
对于串\(S\),若它的最小后缀是它本身,则它是Lyndon串。等价于它是它循环移位中最小的一个。
定理:若\(u,v\)是Lyndon串,则\(u+v\)是Lyndon串,当且仅当\(u< v\)。
定理:我们可以把任意串唯一划分为\(v=v_1^{q_1}+v_2^{q_2}+…+v_k^{q_k}\)的形式,满足\(v_i\)是Lyndon串,且\(v_i>v_{i+1}\)。
构造:掉线了。
后面的例题:也掉线了。
标签:树分治 size 一段 log 随机 mes 循环 深度 扫描线
原文地址:https://www.cnblogs.com/suwakow/p/11375066.html