字符串 总结
Posted duan-yue
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字符串 总结相关的知识,希望对你有一定的参考价值。
喵星球上的点名:
对于字符串的匹配问题,可以考虑把文本、模式串串起来,然后处理SA数组。中间加上不同的“挡板字符”防止两个不同的串被以为是一个串匹配($ab$、$aba$)。但是一个后缀串还是会和另一个串匹配多次。对于点名串,它叫到的名字的$lcp$不小于点名串的长度,那么可以单调栈求控制范围了,对于范围中的点名串,相当与是统计颜色数。可以记录颜色前驱$pre$,主席树差区间$[l,r]$中$pre$比$l$小的个数;也可以通过枚举询问的右端点,对于同一个点名串只维护最右的一个,相当于减少了一维,就可以用树装数组了。对于一个名字被叫到的次数,也可以考虑确定一个边界来查询。设点名串的控制区间为$[l,r]$,名字$x$的前驱为$pre[x]$。一个点名串能给名字做贡献,其实就是$pre[x] le l le x$,画图容易理解。 就是说,如果一个点名串的r小于了当前$x$,一定不能贡献了,就可以删除贡献。这样可以吧点名串的贡献计在$l$上,姓名串查询$(pre[x],x]$的贡献,当一个$r > x$时就失效,可以数状数组维护了。
差异:
SA:
对于$len(i)$总贡献就是$ans=frac{(N-1)*N*(N+1)}{2}$,减掉的$lcp$考虑每个后缀的$lcp$出现多少次。枚举范围$i eq j$那么就是任意点对都会枚举到,所以以$rank$排序后考虑是一样的。那么求每个$height$能控制的范围就是这一长度的$lcp$的次数。用单调栈。
SAM:
同样的,考虑SAM中的前缀的形式:两个串从根节点开始最长的重叠部分就是$lcp$。还是考虑$lcp$的次数。对于从根节点开始的公共部分,可以维护$g[x]$表示根到$x$的路径的总长度。枚举第一个分叉点$x$,从$x$开始分叉,维护$f[x]$表示从$x$开始到一个终止节点(可以从$N$点的$last$向上跳父亲标记)的路径数。$dp$合并时,来自同一$to$的点对不能贡献,所以$ans-=g[x]*(C_{sum f[to]}^{2}-sum C_{f[to]}^2)$。
生成魔咒:
SAM:
对于一个字符串的本质不同子串数,可以建SAM后$dp$得到。加入修改后,在原来基础上并不好直接修改$dp$值,所以考虑一次建完整个串,再在SAM上分部分统计贡献。由于是顺序加入字符并统计,在某一时刻的答案其实就是总串中前几位的答案,那么子串能产生贡献,末尾就要出现在时间点之前,也就是相应的$endpos$中最小的位置在时间点之前(存在一个即可,所以是最小的$firstpos$)。建$ParentTree$按$firstpos$统计答案。
品酒大会:
SAM:
题意概要:对于点对$(a,b)$,若在串$S$中后缀$a、b$的最长公共前缀为$lcp$,那么他能为$ans1[0 o lcp]$做$1$的贡献,为$ans2[0 o lcp]$更新最大值。考虑建SAM,在SAM上,两个后缀的$lcp$体现在其在从根开始匹配的路径的公共长度,而到一点的路径长的种数不一,所以并不好计算$lcp$的贡献。我们再考虑ParentTree的意义,在PT上从一个点跳到它的父亲表示寻找某串的后缀(某串是符合那点$endpos$的串),那么两串在PT上的$lca$节点实际上表示两串的公共后缀。我们倒向建SAM,$lca$就是$lcp$了。倒向的$endpos$就是原串的起点,若一点$len$的范围为$[l,r]$,那么就是说,它的任何一个$endpos$为起点,一定可以向后(原串方向)延伸出相同的[l,r]长度的串,这些串有[l,r]的公共前缀。由于本题统计点对而不是统计子串个数,那么我们从PT中一点的endpos任选两个起点,它能往后匹配$[l,r]$长度,就可以为$ans1[l o r]$做$1$贡献。这样区间加贡献出来的答案不需要再做后缀和,因为对于我们选中的$endpos$的两点,虽然它只做了$[l,r]$的贡献,但是PT上它的父亲节点的集合也包含它的$endpos$集合,且$len<l$,PT上它的儿子的集合含于他的集合,且$len>r$,所以说从任何两个起点开始,向后延伸的所有能匹配的长度都可以统计到。求最大值也是类似的,在PT节点上维护$endpos$的最大、次大、最小、次小即可。如果最后作最大值的后缀$max$的话,这里就可以不作区间取$max$了,只要计在$maxlen$的答案中就好了。
SA:
用SA解决$lcp$就比较简便了,我们求出$height$后,按$rank$排序,用单调栈求出一个点$x$的控制区间(以它的$height$为最小的区间)。对于那个区间,如果选了$x-1$,那么再选$[x,ri[x]]$都是$height[x]$为$lcp$;或者如果选了$x$,那么再选$[le[i],x-1]$都是$height[x]$为$lcp$。这样方案数可以直接算得,点对最大权值就可以ST表区间查询,并且只用维护美味度最大、最小值。
以上是关于字符串 总结的主要内容,如果未能解决你的问题,请参考以下文章