Strings
Stirng
好久没有更过日志了,随便补一点题。
如果您点看来了建议不要往下阅读,因为本垃圾的题目您肯定都是可以做到大喊这是典。
P4248 $\surd$
前面两个可以直接计算,考虑后面的 $lcp$。
构造后缀数组,因为有 $lcp(S_{sa[x]},S_{sa[y]})=\min\limits_{x\le k\le y}ht[k]$ 之后考虑每个 $ht$ 的贡献,直接单调栈维护即可。
P1117 $\surd$
才自己之前是二分 + 哈希 + 打表过的。
考虑正经解法,首先我们把 $AA$ 和 $BB$ 分开来考虑,因为他们的结构是一样的。不放设 $f_i$ 表示以 $i$ 结尾的 $AA$ 形式结构,$g_i$ 表示以 $i$ 开头的结构方案数。那么答案就是
$$ \sum f_{i-1}\times g_i $$
考虑怎么计算,有同学提出一个比较暴力的方法,本人太菜一直认为很奇怪。
考虑对于每个位置作为中间的情况,这时候相当于要求其前缀反过来和后缀的 $lcp$。
考虑对于每个点把前后缀都拎出来,先单独在前后缀里面排序,这下会有两个排好序的字符串,之后直接归并 $2n$ 次可以解决,比大小的过程中直接二分 + 哈希。然后考虑 $lcp$ 的问题,因为是有序的,可以理解成 ht 数组的形式,记录两两之间的 $lcp$ 即可。
这种做法是自然的,但是稍微有点麻烦,通过思维可以简化这个过程。
考虑枚举 $A$ 长度,对于每个长度倍数的位置打一个断点,一个合法的 $AA$ 显然一定经过恰好两个断点。
分析两个断点,设其后缀的 LCP 为 $x$,前缀的 LCS 为 $y$。那么两个断点有贡献当且仅当 $x+y\ge len$。贡献就是 $AA$ 的终点可以取在重合的部分。画图可以理解。
P5028 $\surd$
考虑拼在一起之后跑一下后缀数组,对于 $s,t$ 相当于在求 $\max\limits_{x\in s,y\in t}\text{lcp}(\text{suf}_x,\text{suf}_y)$。再次考虑 lcp 求的过程其实是取最小值,因此每次肯定尽量选两个排好序之后相近的字符串。直接记录即可。
注意空间限制。
P2178 $\surd$
缝合。
构造后缀数组之后对于第一个答案统计是显然的,对于每个 hight 考虑其管理的区间,每次题目中要求的限制减小一个就考虑等于这个的 hight 位置的贡献。
之后对于第二个答案统计相当于每次询问两个区间,从这两个区间里面各取一个数,要求两个数字的乘积最小。这个用线段树维护即可。
似乎第二个答案有别的做法,但是这个方法是比较简单实现的,可能略有一点长。
P8023 $\surd$
题解开早了。
这题其实不需要用后缀数组,首先显然需要对于每个字符维护一个 $nxt$ 指针指向下一个和其不一样的字符。
当 A,B 目前最前面的字符一样的时候,考虑其指向的字符:
如果两者指向的字符都大于本身,那么不影响顺序,随意填即可。
否则如果两个指向的字符一个大于一个小于,显然先选择小于的。
最后如果都是小于,那么先考虑距离,肯定会先跑距离更小的一个。如果距离相等同样对其本身大小进行比较,如果还是相等,这时候就要考虑往后再跳一次。注意为了避免每次跳的复杂度过大,可以用类似并查集的形式对其进行维护。