CF1393E2 - Twilight and Ancient Scroll (harder version)
CF1393E2 - Twilight and Ancient Scroll (harder version)
题目大意
给定 \(n\) 个串 \(S_i\) ,求在每个串中至多删除一个字符(可以删到空)
最终 \(S'_i\) 字典序单调不减的方案数
dp
显然是记录上一个串删除的位置 \(j\) ,得到 \(dp_j\) ,依次考虑每个串
设 \(S\) 为当前串, \(T\) 为上一个串
每次我们枚举当前串删除的位置 \(i\) ,不妨设得到的新串为 \(S'\) ,考虑对于 \(S'\) 找到所有合法转移
设 \(L=LCP(S,T)\) ,在 \(T\) 中删除位置为 \(t\)
- \(t>L+1\)
则可以根据 \(T_{L+1}\) 和 \(S'_{L+1}\) 的关系确定 \(T'\) 与 \(S'\) 的关系,只需要处理一个后缀和 \(suf_i\)
2.设 \(p\) 为 \(T_{L+1}\) 向前延伸且字符相同的最长位置, \(t\in[p,L+1]\)
此时,删除 \(T_t\) 可能会使得 \(L'>L\) ,所以提出来特殊处理
显然 \(t\in[p,L+1]\Leftrightarrow t=L+1\) ,那么对于得到的新串可以再求 \(LCP(S',T')\) 来判断大小
只需要一个区间和
- \(t<p\) ,此时 \(L'=LCP(S',T')<L\)
由于 \(L'<L\) ,比较 \(S',T'\) 相当于比较 \(T_{t:},T_{t+1:}\)
其中 \(T_{t:}\) 表示 \(T\) 在 \(t\) 开始的后缀,那么预处理找到所有合法的 \(t\) ,累前缀和即可得到 \(pre_{p-1}\)
关于实现
写 \(\text{SA,SAM}\) 就完蛋了
由于删除一个字符之后,求 \(LCP\) 的两个串就是在原串基础上进行 \(\pm 1\) 的偏移
线性预处理三个 \(LCP\)
数组即可,当然真正求的时候需要分类讨论一下(真的,就一下/md)
判断 \(T_{t:},T_{t+1:}\) 容易倒着线性预处理出来,在代码里是 \(chk_i\)
所有操作均可以线性处理,时间复杂度为 \(O(L)\) ,77ms
Tips:
比较过程中容易出现奇妙的越界,我写得很丑
1 | const int N=1e6+10,P=1e9+7; |