题目传送门
分析:
最暴力的做法,A向可以控制的B连边,B向以它为前缀的A连边
然后拓扑排序求一条路径的最大值
复杂度\(O(n^2)\)
明显要优化连边,这里给出两种解法:
SAM优化建边:
这里要前缀关系,我们反向建SAM将其变成后缀关系
对于每个串\([l,r]\),我们先找到\(r\)结尾的前缀在SAM上的位置,通过Parent树上倍增找到\([l,r]\)所在的endpos集合的点
对于每个Parent树上的点,维护一个vector,保存在这个点上的A和B
同一个点上的A和B,先按len为关键字从小到大排序,再将B优先放前面,A优先放后面
每个点向它子串集合中最短的连边,B向比他长的并且比下一个B短的A连边,Parent树父亲集合中最长的串向儿子连边
再把控制关系连上去
然后直接跑拓扑排序,时空复杂度都会从\(O(n^2)\)变成\(O(n)\)
写起来细节挺多的有点恶心
后缀数组+主席树优化建边:
我们先用原串跑一次后缀数组
B是A的前缀只需要\(min_{i=rk[lB]+1}^{rk[lA]}height[i]\geq len[B]\)
我们对于每个B,满足上述关系的一定是一个包含\(lB\)的区间
这个可以二分+\(O(1)\)RMQ解决
然后线段树优化建边?不行
发现A的长度如果小于B就会出现问题
那就用主席树
把子串长度从大到小排序,一个一个加入再优化建边就可以了
然后把控制关系也加进去
跑拓扑排序,但是时空复杂度都是\(O(nlogn)\),很卡常
代码是第一种做法的:
(后缀数组是个好东西,我有头发的时候天天写)
#include
#include
#include
#include
#include
#include
#include