P4022 [CTSC2012]熟悉的文章

容易发现 LL 是可以二分的。

接着考虑二分如何 check

比较容易思考的思路是 DP,设 fif_i 表示前 ii 个字符的熟悉子串最长的长度之和。设当前二分的是 LL,那么 fi=max{fi1,maxj[imaxleni,iL]fj+(ij)}f_i = \max\{f_{i-1},\max \limits_{j \in [i - maxlen_i,i-L] } f_j + (i-j)\}。其中 maxlenimaxlen_i 表示以 ii 结尾的最长的在字符串中出现过的字符串的长度。

也就是说,我们可以枚举每一个 jj 进行转移,因为有 [imaxleni,iL][i - maxlen_i,i-L] 的限制,每个从 j+1j+1ii 的字符串一定是在标准作文库中出现过的,转移即可。

maxlenimaxlen_i 可以建出 SAM 后用求最长公共子串的做法维护。

可以获得一个 O(mn2logn)O(m n^2\log n) 的做法。

容易发现 DP 有决策单调性,单调队列维护即可。

posted @ 2023-03-04 14:22  HappyBobb  阅读(7)  评论(0)    收藏  举报  来源