第二次巴蜀做题记录
先挂一下自己写的字符串学习的总结
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