2021.2 BS集训做题记录
第二次巴蜀做题记录
先挂一下自己写的字符串学习的总结
Z函数(扩展KMP)&前缀函数的总结~ - NuoCarter - 博客园 (cnblogs.com)
Problems
\(Z\) 函数板子题。
虽是一道红题,但可以 \(Z\) 函数可以在 \(O(n)\) 预处理,再 \(O(n)\) 得出答案。
而前缀函数可以在 \(O(n)\) 预处理的情况下,\(O(1)\) 得出答案。
相较之下前缀函数做循环节的话要更加nb,当然,前提是最短循环节。
首先“完美子串”的定义就限制了长度为 \(len\) 的完美子串有且仅有一种,那么我们用 \(Z\) 函数可以得出每一个完美子串的长度。
那么难点就在于子串出现的次数了,但是根据 \(Z\) 函数的定义,我们可以知道当一个位置 \(i\) 的 \(Z_i == x\) 时,相当于长度为 \([1,x]\) 的完美子串(前缀)在 \([i,i+x-1]\) 这个区间中出现了一次。 那么可以再这个位置打上一个差分标记,倒叙遍历得出每一个串的次数即可。(线段树当然也珂以)
复杂度 \(O(n)\)
首先一个在前缀和后缀中出现的字符串都是至少出现两次的。于是这道题和上一道题一样,在中间出现的话只需要出现次数 \(\geq3\) 就可以了。同一份代码加个几行就能过。
复杂度 \(O(n)\)
题意:
就是加最少的字母,使得原串变为一个回文串。
设当前的字符串为 \(S\)
\(S\) 一定可以被分成两部分 \(A\),\(B\)。
其中\(B\)是一个回文串(也可以是一个空串),\(A\) 是一个普通的字符串。
设 \(A\) 的反串为 $ A'$
而且 \(A+B+A'\) 一定是一个回文串(想一想为什么)
那么我们加上的字符串就是 \(A'\)
因为\(|A'|\) = \(|A|\),\(|A|=|S|-|B|\)
因为\(|S|\)一定,为了让\(|A'|\)更小,所以需要找到最大的\(|B|\)
也就是找出 \(S\) 的后缀中最长的回文串。
这个利用 \(ExKMP\) 很容易解决
将 \(S\) 的反串 \(S'\) 与 \(S\) 拼在一起,对于一个位置 \(i\) ,如果\(Z_i=SIZ-i\),那么这就是一个合法的后缀回文串
放一个图方便理解吧:
记住,我们找的是最长的后缀回文串,也就是 \(|B|_{max}\)
但答案需要的是\(|A|\),并且还要将 \(S[0\)~\(|A|\)-\(1]\)倒过来输出
最后输出就可以了。
复杂度还是 \(O(n)\) 的。
P6080 [USACO05DEC]Cow Patterns G
在很多普通的字符串匹配中,\(\pi\) 函数表示的是前缀中最长的 \(border\) ,也就是前缀中前后缀相等的最长长度。
但在这道题中,很明显,无法用相等来表示。
首先,将模式串(\(K\) )和数字串(\(N\))拼起来,中间插入一个特殊符号 “#”。
根据题意:我们应该将 \(\pi\) 函数中的“相等”看做大小关系相同,于是$ \pi[i]$ 就表示当前 \(S[0\)~\(i]\) 中前后缀大小关系最长的长度,因为有个特殊符号 “#” ,所以所有的 \(\pi[i] \leq K\),而满足“坏蛋团体”区间的右端点,一定满足 \(\pi[r]=K\)。
那么这时问题就出在了如何判断大小关系相同了。
如果说当前 \(S[0\)~\(j-1]\)与\(S[i-j,i-1]\) 大小关系相同。
那么对于 \(j\) 与 \(i\) 这两个位置,(首先匹配时这个 \(j\) ,一定是\(\leq K\)的)
如果说 \([0,j-1]\) 中 比\(j\) 大的数与\([i-j,i-1]\)中比 \(i\) 大的数的个数相等
而且 \([0,j-1]\) 中 和\(j\) 相等的数与\([i-j,i-1]\)中和 \(i\) 相等的数的个数相等
又因为两个区间长度是一样的,那么区间中大于 \(j\) ,与大于 \(i\) 的数的个数也是相等的。
那么这\([0,j]\) 与 \([i-j,i]\)两个区间的大小关系相等。
如此我们只需要用一个桶的前缀和,就可以在 \(O(S)\) 的复杂度中求出区间中比它小的与相等的数的个数了。
Warning : 最后需要的是左端点,但利用 \(\pi\) 函数判断的话,符合条件的是右端点.
复杂度还是 \(O(n)\)。
因为字母表s长度很小,所以暴力枚举每一种文本串,对每一个串做一次kmp
首先有向无环图,考虑拓扑排序,接下来按照 \(BFS\) 来理解整个拓扑排序。
相当于把所有的点分成了若干层,(即每一层中的点互不联通)。
那么保留最少的边一定是将每一层形成一条链的关系,也就是应该优先保留 \(u\) 能够到达的更浅的层。
于是对于当前的点 \(u\) ,每一条边按照出点 \(v\) 的时间戳排序。
因为是最优策略,所以按照上面的次序访问边 \(u->v\) 如果说 \(u,v\) 已经联通,这个边可以删去,连通性和最优性都可以保证。
P2881 [USACO07MAR]Ranking the Cows G
总的大小关系有 \(\frac{n*(n+1)}{2}\) 种。查询的最小次数就是不重复查询。
一开始就用 bitset
维护一下关系个数然后用 \(\frac{n*(n+1)}{2}-\) 总的联通个数就好了。
经典平衡树板子
对编码离散化后对每个编码建立一颗平衡树,用无旋Treap很好实现。
查询时输出 \(R\) 的排名减去 \(L-1\) 的排名就可以了。
P4402 [Cerc2007]robotic sort 机械排序
P3521 [POI2011]ROT-Tree Rotations