(FJWC2020)DTOJ 4680. 红黑兔

题意

上个月,PinkRabbit 在算法竞赛网站 Codeforces 一把打上了 ILGM。

PinkRabbit 现在看到了一道简单题,但他忙于水知乎夺取 Codeforces 世界榜首,于是把问题交
给了你:

给定一个长度为 n n n 的只包含小写英文字母的字符串 s s s,你需要找到一个最大的 k k k ,使得存在:
1 ≤ l 1 ≤ r 1 < l 2 ≤ r 2 < l 3 ≤ r 3 < ⋯ < l k ≤ r k ≤ n 1 \le l_1 \le r_1 < l_2 \le r_2 < l_3 \le r_3 < \cdots <l_k \le r_k \le n 1l1r1<l2r2<l3r3<<lkrkn

(即 k k k 个区间 [ l 1 , r 1 ] [ l 2 , r 2 ] ⋯ [ l k , r k ] [l_1,r_1][l_2,r_2] \cdots [l_k,r_k] [l1,r1][l2,r2][lk,rk] 的左右端点都递增且两两不相交)

使得对于每个 1 ≤ i < k 1 \le i <k 1i<k ,都满足 s [ l i + 1 ⋯ r i + 1 ] s[l_{i+1} \cdots r_{i+1}] s[li+1ri+1] s [ l i ⋯ r i ] s[l_{i} \cdots r_{i}] s[liri] 的严格子串。

其中 s [ l ⋯ r ] s[l \cdots r] s[lr] 表示字符串 s s s 的第 l l l 到第 r r r 个字符组成的字符串。

字符串 A A A 是字符串 B B B 的严格子串,当且仅当从 B B B 的开头和结尾各删掉若干个字符(从开头和结尾
删掉的字符个数都可以是零个,但删掉的字符个数之和必须大于 0 0 0)能够得到 A A A

子任务1 (10 分): n ≤ 100 n \le 100 n100

子任务2 (15 分): n ≤ 1000 n \le 1000 n1000

子任务3 (25 分): n ≤ 3 × 1 0 4 n \le 3 \times 10^4 n3×104

子任务4 (30 分): n ≤ 1 0 5 n \le 10^5 n105

子任务5 (20 分):无特殊限制。

对于所有的数据,有 1 ≤ n ≤ 5 ∗ 1 0 5 1 \le n \le 5*10^5 1n5105 ,字符串仅包含小写英文字母。

题解

考虑暴力,从后往前,记 f [ i ] [ j ] f[i][j] f[i][j]为最后一段为 [ i , j ] [i,j] [i,j]的最大答案,转移时枚举下一个和它相同的串,显然只拓展一位是最优的,效率 O ( n 3 ) O(n^3) O(n3)。(考场做法,竟然过了 n = 1000 n=1000 n=1000的点)。
考虑优化,改为被动转移,将可以转移过来的值记在哈希表上即可做到 O ( n 2 ) O(n^2) O(n2)(然而不能多得分) 。其实注意到既然最优答案的每个串长度依次是 1 , 2 , . . . , k 1,2,...,k 1,2,...,k的(所以最后一个串长=答案),这样串的长度不会超过 n \sqrt{n} n ,效率可以优化为 O ( n n ) O(n\sqrt{n}) O(nn )(正解和这个并没有关系) 。考场上这两者都没想到很不应该。
发现瓶颈在于状态数,考虑是否需要那么多状态。对于一个结尾,它的最大答案是单调的:即如果可以为 x x x,则一定也可以比 x x x小(每个串都去掉开头或都去掉结尾即可少1)。利用这个优化状态:记 f [ i ] f[i] f[i]为以 i i i为结尾的最大答案,转移时,直接二分 f [ i ] f[i] f[i]判断是否合法,则合法的转移点 j j j应满足:
1. j > i + f [ i ] j>i+f[i] j>i+f[i]
2. f [ j ] ≥ f [ i ] − 1 f[j]\ge f[i]-1 f[j]f[i]1
3. f [ i ] ≤ l c p ( i , j ) f[i]\le lcp(i,j) f[i]lcp(i,j) f [ i ] ≤ l c p ( i + 1 , j ) f[i]\le lcp(i+1,j) f[i]lcp(i+1,j)
用主席树+SA可以维护,效率为 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)
考虑利用单调性来避免二分:类似 f [ i ] f[i] f[i]的单调性,可猜想并证明 f [ i ] ≤ f [ i + 1 ] + 1 f[i]\le f[i+1]+1 f[i]f[i+1]+1,于是直接推指针即可,效率 O ( n l o g n ) O(nlogn) O(nlogn)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值