• [DP][SA][可持久化线段树]黑红兔


    • 源自 xyz32768 菜鸡的 FJ 省冬令营模拟赛题

    • 原题 CF1063F

    Statement

    • 给定一个长度为 (n) 的字符串 (s),仅包含小写英文字母

    • 要从中从左往右选出若干段不相交的子串

    • 使得选出的这些串中,每个串都是上一个串的严格子串

    • 求最多能选出多少段

    • (1le nle5 imes10^5)

    Solution

    • 首先注意到一个性质:设选出的第一个子串长度为 (len),那么最优解选出的子串长度一定是 (len,len-1,dots,2,1)

    • 于是从右往左 DP:(f[i][j]) 表示以 (i) 为首串的开头,是否存在选出 (j) 段的方案(也是首串的长度为 (j)

    • 这个 DP 是 (O(n^2))

    • 我们还有一个性质:(f[i][j]) 是单调的。换句话说,如果存在选出 (j) 个串的方案就一定存在选出 (j-1) 个串的方案

    • 证明考虑第一个串 (t) ,如果选出的前 (k) 个串都是 (t) 的后缀,而第 (k+1) 个串是第 (k) 个串的前缀,那么我们可以把前 (k) 个串都删掉最后一个字符,第 (k+1) 个串直接扔掉,这样就构造出了一个选 (j-1) 个串的方案,特殊情况 (k=j) 时把所有串都删掉最后一个字符并把最后一个串(长度已经变成 (0))扔掉

    • 于是可以重新定义 (f[i]) 表示以 (i) 为开头最多选出多少个串

    • 根据上面的结论,可以二分 (f[i]),转化成判断是否存在 (jin[i+f[i]dots n]) 使得 (max( ext{lcp}(i,j), ext{lcp}(i+1,j))ge f[i]-1)(f[j]ge f[i]-1)

    • 易得建出 SA 之后,满足 ( ext{lcp}(i,j)ge f[i]-1)(rank_j) 是一段区间,可以二分 + RMQ 求出这个区间之后,利用可持久化线段树求得该区间内的 (f[j]) 最大值,( ext{lcp}(i+1,j)) 同理

    • 这样的复杂度是 (O(nlog^2n))

    • 注意到另一个性质:(f[i+1]ge f[i]-1),证明类似上一个结论

    • 于是把 (f[i]) 设成 (f[i+1]+1) 之后不断检查当前的 (f[i]) 是否合法,如果不合法就一直 (f[i]--)

    • 易得 (f[i]--) 的次数之和不超过 (O(n)),所以总复杂度 (O(nlog n))

    • 现场 (O(nlog^2n)) 甚至 (O(nsqrt n)) 小常数过了,声名狼藉 QAQ

    Code

    • 咕咕咕
  • 相关阅读:
    win7共享文件
    Linux之samba服务
    Linux之Apache服务
    Linux之ssh服务
    Linux基础入门之管理linux软件(rpm/yum)
    Linux基础入门之文件管理类命令
    PHP ssh链接sftp上传下载
    Black Hat Python之#2:TCP代理
    Black Hat Python之#1:制作简单的nc工具
    使用python的socket模块进行网络编程
  • 原文地址:https://www.cnblogs.com/xyz32768/p/12230395.html
Copyright © 2020-2023  润新知