其实可以用 SA/SAM 写,但是我又忘了这俩咋写了 QwQ
# 题意
(既然是中文的题面……)
> 洛谷 P1117
# 解析
由于题目要求找 AABB
式的子串,那么我们可以这样计算——找到一个位置 $i$,然后 $i$ 左边找 AA
、右边找 BB
,根据乘法原理乘起来就好了。
也就是说要对每个位置 $i$,计算 $l_i,r_i$ 分别表示以 $i$ 开始的 AA
(就是 BB
,反正形式上是一样的) 的数量和以 $i$ 结束的 AA
的数量。那么答案就是 $\sum l_ir_{i+1}$。
考虑如何迅速计算 $l_i,r_i$。
不妨先枚举 A
的长度 $L\in[1,\frac n2]$,然后把字符串上位置 $L,2L,3L,\dots$ 都打上标记 —— 于是我们发现,任何一个长度为 $2L$ 的 AA
上都有恰好两个位置有标记。
知道这一点有什么用呢?我们枚举相邻两个被标记的位置 $iL,(i+1)L$,想要求经过这两个位置的长度为 $2L$ 的 AA
有哪些。方法就是求 $\Big((i-1)L,iL\Big]$ 和 $\Big(iL,(i+1)L\Big]$ 的最长公共后缀(LCS)、$\Big[iL+1,(i+1)L\Big)$ 和 $\Big[(i+1)L+1,(i+2)L\Big)$ 的最长公共前缀(LCP)。
> Hint. 一定要看清楚这几个串的范围,要不重不漏
画张图可能就好理解了——
> Update. 我怎么把 LCS 写成 LCA 了 (;′⌒`)
emm……可能需要两张图:
其实已经比较清晰了——我们求出左端点可以取的范围 $[l_1,r_1]$ 和右端点可以取的范围 $[l_2,r_2]$,然后 $l_{[l_1,r_1]}$ 都 +1,$r_{[l_2,r_2]}$ 都 +1,只用差分就好了。
至于怎么求 LCP/LCS,可以用 SA/SAM,但是我忘了怎么写,还好 $O(n\log^2n)$ 能过,可以用哈希+二分来求。
> Hint. 复杂度的话首先是 $O(n)$ 枚举 $L$,然后有 $O(\frac nL)$ 个有标记的位置,每相邻两个标记位置要 $O(\log n)$ 求 LCS,LCP,于是结合求和级数的简单知识,可以知道复杂度是 $O(n\log^2 n)$。
# 源代码
1 | /*Lucky_Glass*/ |