传送门
Description
现有一个字符串 \(S\)。
从中划出 \(n_a\)个子串作为 \(A\) 类串,第 \(i\)个(\(1 \leqslant i \leqslant n_a\))为 \(A_i = S(la_i, ra_i)\)。
类似地,划出 \(n_b\)个子串作为 \(B\) 类串,第 \(i\)个(\(1 \leqslant i \leqslant n_b\))为 \(B_i = S(lb_i, rb_i)\)。
给定 \(m\) 组支配关系,每组支配关系 \((x, y)\) 描述了第 \(x\) 个 \(A\)类串支配. 第 \(y\)个 \(B\) 类串。
求一个长度最大的目标串 \(T = t_1+t_2+· · ·+t_k\)(\(k⩾0\))满足:
- 分割中的每个串 \(t_i\) 均为\(A\)类串
- 对于分割中所有相邻的串 \(t_i\), \(t_{i+1}\)(\(1 \leqslant i < k\)),都有存在一个\(t_i\)支配的 \(B\) 类串,使得该 \(B\) 类串为 \(t_{i+1}\)的前缀。
输出这个最大的长度。如果存在无穷大的长度,则输出\(-1\)
Description
题意就是:我们要找到每个\(A\)类串是否能作为另一个串的后继,连边,跑最长路,如果有环就输出\(-1\)
重点在于如何优化连边:
- 线段树优化连边?其实是可以的
- 前后缀优化连边?想太多
- *后缀树优化连边?就它啦
我们的连边方式其实上是,\(A\)类串向其能够支配的\(B\)类串连边,然后\(B\)类串再向能作为其前缀的\(A\)类串连边,显然,我们在\(B\rightarrow A\)上进行优化
优化\(1\):考虑到较小的\(B\)类串可以向较大的\(B\)类串连边,就可省去部分\(B\rightarrow A\)的边
把前缀换成后缀,也就是处理原串的反串,建出它的后缀自动机
然后我们就能得到一棵\(parent\)树,这棵树上每个节点所带表的串是其子树内其它串的后缀
那么也就是原串中的前缀
首先,我们对于每个\(A\)、\(B\)类串,找到它在后缀自动机上的位置,显然有可能有多个串位于同一个位置,怎么找位置呢,倍增就行啦
优化\(2\):对于\(parent\)树上的父节点,向其子节点连边
但是有可能有多个串处在同一个节点上,把点按照大小排序,相同长度的\(A\)类串位于\(B\)类串之后,然后每个\(B\)串只向长度大于等于它的且小于下一个\(B\)串的\(A\)类串连边,只需最后一个\(B\)类串向子节点的第一个\(B\)串连边即可。
Code
咕咕咕
Blog来自PaperCloud,未经允许,请勿转载,TKS!