P4022 [CTSC2012]熟悉的文章

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

接着考虑二分如何 check。

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

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

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

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

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

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