Runs 学习笔记

定义一个字符串 \(|S|\) 里的一个 run,指其内部一段两侧都不能扩展的周期子串,且周期至少完整出现两次。

严格地说,一个 run 是一个 三元组 \((i,j,p)\),满足 \(p\)\(S[i..j]\) 的最小周期,\(j-i+1 \ge 2p\),且满足如下两个条件:

  • 要么 \(i=1\),要么 \(S[i-1]\ne S[i-1+p]\)
  • 要么 \(j=n\),要么 \(S[j+1] \ne S[j+1-p]\)

性质一:\(|\{(l,r,p)\}|\)\(\mathcal{O}(n)\) 级别的。

性质二:\(\sum\frac{r-l+1}{p}\) 也是 \(\mathcal{O}(n)\) 级别的。

性质三:\(\sum r-l+1-2p\)\(\mathcal{O}(n\log n)\) 级别的。

性质四:Runs on sam (我取的神秘名字)


怎么求出所有的 runs?

考虑进行 优秀的拆分 的套路,先求出所有的“伪 Runs”(两边不能再拓展,但是周期不一定是最小)。

注意到这些“伪 Runs”只是 \(p\) 不对,于是对于所有 \((l, r)\) 保留最大的唯一的 \(p\)

第一步求的伪 Runs 是 \(\mathcal{O}(n)\) 的,第二步进行基数排序可以减小常数。

感觉实际上直接用个 map<pair<int, int>> 去重就,差不多得了。


例题一:区间 \(A^2\) 串计数(不要求本质不同)

分两种,若 Runs \(l, r\) 被区间 \(L, R\) 完全包含,则可以用扫描线计算贡献。否则,相当于和区间相交于 \(L-1\)\(R+1\),这种 Runs 共有 \(\mathcal{O}(\log n)\) 个,直接拿出来求贡献即可。

例题二:区间本质不同 \(A^k(k\ge 2)\) 串计数

Runs on sam

例题三:区间本质不同 \(A^2\) 串计数

求出所有 Runs。

对于一个询问 \(l, r\),将有贡献的 Runs 分成两种:

  • \(R\le r\)
  • \(R>r\)

对于第一种,我们扫描线维护,由于我们扫的时候能确定这个 Runs 内所有的本质不同 \(A^2\) 串的出现位置,所以我们直接用树状数组维护即可。

第二种只有 \(\mathcal{O}(\log n)\) 个。

所以我们扫描线,扫到 \(r\) 的时候找出所有包含 \(r\) 的 Runs 中的最长 \(A^2\) 串,消去它之前的贡献,然后把所有以 \(r\) 结尾的 Runs 的贡献加到 BIT 里。

核心思想是一口去处理单个 runs 内的所有的 \(A^2\) 串。(需要维护一个 \(A^2\) 串最后出现在哪个 Runs 里,而不是具体位置)。


部分做法需要一个称之为 「斜线加,矩形求和」的东西。

即:在一开始给出若干条射线,从 \((x, y)\) 开始向右上,斜率为 \(1\)

最后有若干次矩形查询。

考虑将矩形查询分成跨过一条平行 \(x\) 轴的线和平行 \(y\) 轴的线。

不妨以跨过平行于 \(y\) 轴的线为例。

\((x, y)\)\((X,0) - (X,Y)\) 的条件为

  • \(x\le X\)
  • \(y+X-x\le Y\),变形后得 \(y-x\le Y-X\)

贡献是 \(X-x\)。则我们可以用一个线段树维护这个过程。

过平行于 \(x\) 轴的线类似。(以上皆为口胡,因为笔者并没有真正写过这个做法)。

斜线加矩形求和将成为时代的眼泪。—— 我。

posted @ 2024-07-25 19:35  fjy666  阅读(331)  评论(0)    收藏  举报