【A】字符串
P4696 [CEOI 2011] Matching
要求子串内的相对大小顺序,类似定义 border,那么可以树状数组求 rnk,然后 kmp 处理。
求 rnk 有点浪费,不如考虑每次加入一个数的时候检查插入到的那个 \(a<b\) 的边是否仍然满足条件。
企鹅游戏
ACAM,暴力跳 fail 链统计(每次找到第一个祖先是终止节点),复杂度 \(O(L\sqrt L)\)。
考虑一个设阈值 \(B\),\(|s_i|\le B\) 的串至多出现 \(LB\) 次,而 \(|s_i|>B\) 的串至多有 \(\frac{L}{B}\) 个,且至多在 \(\frac{L}{B}\) 个串中出现过,则有 \(LB+\frac{L^2}{B^2}\le L^{\frac{4}{3}}\)。
则对于所有询问,\(c_i>0\) 的位置只有 \(O(L^{\frac{4}{3}})\) 个。
那么我们每次暴力建出虚树然后往上合并 \(occ\) 即可。
CF710F String Set Queries
二进制分组建 ACAM,然后开两个去维护所有串和删除的串。
CF1483F Exam
ACAM,每个 \(s_i\) 的前缀只会至多找到一个最长的 \(s_j\) 是可能造成贡献的。
那么要求一个 \(s_j\) 没有被其他的 \(s_j'\) 覆盖即可。
我们可以统计每个 \(s_j\) 没被覆盖的次数和在 \(s_i\) 中出现的总次数。
>.<
将这些给定路径建出 ACAM,然后在这个 ACAM 上跑最短路。
\(\color{Red}\mathtt \Gamma\)
Boring Problem
考虑在 ACAM 上随机游走,那和单串 border 游走是类似的。
\(E(u)=1+\sum_{c} p_cE(\delta_{u,c})\)。
考虑每个节点往他儿子递归的时候,需要新建 \(\deg-1\) 个变量。那么最后只有 \(O(n)\) 个变量,可以消元求出。
P3546 [POI 2012] PRE-Prefixuffix
重新排列:\(s_1 s_n s_2 s_{n-1}s_3s_{n-2}...\)
那么 border 变成了回文串。manacher 可以做。
P9482 [NOI2023] 字符串
建 \(s+\mathsf{inf}+\mathsf{rev}(s)\) 的 SA,那么 \((i,l)\) 合法要求:\(suf_{i}<suf_{m-(i+2l-1)+1}\)。
但是可能有相等的情况,他是回文串,统计一下即可。
CF1827C Palindrome Partition
考虑每个合法串一定可以通过一直删除最小偶回文后缀得到。递推做。
P2178 [NOI2015] 品酒大会
根据 height 从大到小加入维护连通块,第一问直接做,第二问直接做。
拜神
二分答案,在 \(suf_{[l,r-mid+1]}\) 中找到两个串的 LCP \(\ge mid\)。
按照 height 从大到小加入,维护连通块,启发式合并找支配点对。
CF700E Cool Slogans
我们规定 \(s_{i}\) 必须是 \(s_{i+1}\) 的后缀。观察到两个节点之间能否转移只关心最长串,可以从上往下 dp。
\(F_u=F_{fa}+[lst 在 u 中至少出现 2 次]\)。
可以使用可持久化线段树维护 endpos 处理。
P6292 区间本质不同子串个数
一个暴力:扫描线,每次对于 \(z_i\) 的 fail 祖先进行区间加减操作,维护每个字符串最后一次出现的左端点。
也就是每次对于某个 \(u\) 的祖先,将他们的 lstR 都设为 \(i\)。
看成 access 操作,每条实链上的 lstR 都相同。用 LCT 维护啦。
CF1063F String Journey
考虑将 \(s\) 反过来,然后规定 \(|t_i|=i\)。那么一定有 \(t_{i-1}\) 是 \(t_i\) 的前缀或者后缀。
考虑强制 \(t_k\) 以 \(i\) 结尾的最大答案为 \(k=f_i\),则 \(f_i-f_{i-1}\le 1\),那么 \(i-f_i\) 单调不降。
则 \(t_k=s_{[i-f_i+1,i]}\) 的左端点也是单调不降的,考虑双指针维护合法性。
\(s_{[l,r]}\) 合法,要求 \(s_{[l+1,r]}\) 或者 \(s_{[l,r-1]}\) 在 \(l\) 左侧作为合法串出现过;\(s_{[l,r]}\) 合法则 \(s_{[l+1,r]}\) 合法。
容易使用 SAM 维护。
P8368 [LNOI2022] 串
有一个下界是 \(n/2\)。
考虑 \(t\) 的路径:l+1,r+2。其中 l+1 后可以往前跳到一个子串相等的地方。
那么一个字符串 \(s_{l,r}\) 若出现 \(2\) 次以上,那么他就有 \(r-l+1+(n-r)/2\) 的贡献。
P4218 [CTSC2010] 珠宝商
考虑点分治,对于每个 \(i\) 求出以 \(i\) 结尾/开头的路径数量,乘法计算 occ。
可以正反 SAM 上走路,每次向前加入一个字符,可能跳 parent tree 儿子,可能不变,可能失配。最后 dfs 下穿到叶子。
考虑会算多同子树内的贡献,每次子树单独做一遍即可。
做一次复杂度是 \(O(m+siz)\) 的,总复杂度 \(O(n\log n+mn)\)。
考虑优化,我们规定递归的子树大小 \(\le \sqrt n\) 的时候暴力 \(O((\sqrt n)^2)\) 统计。那么本题中只有前 8 层不是跑暴力。
UOJ577 打击复读
sol1:拆贡献:\(wl_l\sum_{r=l}^n |\mathsf{endpos}(s_{l,r})|\sum_{i\in\mathsf{endpos}(s_{l,r})}wr_i=wl_l\sum_{r=l}^n F_{s_{l,r}}\),\(F\) 是可以预处理的,而这个求和是一个 DAG 链求和,DAG 链剖分处理。
我不会 DAG 链剖分。
sol2:
sol3:
子串 border
\(\color{Red}\mathtt \Gamma\)
浙公网安备 33010602011771号