[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

  • 咕咕咕
原文地址:https://www.cnblogs.com/xyz32768/p/12230395.html