基础子串结构

参考文献

大概阅读完了。那么写一些要点。
从这个更加机械的角度思考,可能更容易将一些问题做到更优的复杂度。

理论

  • 等价类:
    • ext 相同则在同一个等价类中。ext 是保证 occ 相同的最大拓展串。
    • 等价类的形状:倒阶梯型。
    • 代表元:ext,即左上元素。
    • 出现次数为 occ,每个等价类的周长总和为 \(O(n)\)。
  • parent tree 相关:
    • 正 SAM 上节点与等价类中的行一一对应。反 SAM 也与列有一一对应关系。
    • 正 SAM fail 边若规定从父亲连向儿子,则应该是一行的左侧连向另一行的右侧,其中这两行在平面上是相邻的。反 SAM 同理,从上侧连向下侧。
  • DAG 相关:
    • DAG 边的 \(+c\) 操作可以描述为反 SAM 的跳 parent tree 儿子操作。

构建

  • 先建立 正/反 SAM。
  • 找到代表元:
    • 代表元性质:一定是正/反节点内最长的串。
    • 我们在 正 SAM 上走 DAG 边,要求保证当前串是节点内最长的。同时,维护 反 SAM 上所在的节点,这个我们预处理每个节点前加入 \(c\) 字符会到哪个儿子即可。
  • 给所有行列找到代表元:
    • 对于不是等价类中第一行/列的节点,他们一定只有一条 DAG 出边,且指向它的上一行/列。
    • 我们给他编个号,要求处理到当前节点的时候,出边的代表元已经确定。
    • 事实上根据 SAM 节点编号从大往小扫就好了。
  • 给等价类内部行列排序:直接按照节点编号就是有序的。

例题

CF1817F Entangled Substrings

居然在这里找到了模拟赛题目?!?!
首先给条件做个基本的转化:所有的 \(a,b\) 只能在 \(acb\) 中出现,\(c\) 唯一。
即 \(a,b,acb\) 在同一个等价类中。
考虑按照 \(acb\) 计数,在等价类中从下往上扫行,维护一些前缀和的信息+双指针即可计算。

更详细的做法在这里

UOJ577 【ULR #1】打击复读

可以求出每个 \(wl_i\) 的贡献。
首先考虑等价类中子串 \(s_{x,y}\) 的贡献?他是对应行列的 \((\Sigma vl)\times (\Sigma vr)\times \mathsf{occ}\)。
也就是我们可以先处理出 \(\Sigma vr,\mathsf{occ}\),然后扫列,前缀和+双指针即可维护每个 \((\Sigma vl)_i\) 的系数,然后 pushdown 就好了。

P8351 [SDOI/SXOI2022] 子串统计

就是你从 \((1,n)\) 往右下走,你经过的格子的贡献是它的 \(\mathsf {occ}\),我们走到一个 \((x,x)\) 就停止。
将路径方向改成 \((x,x)\to (1,n)\)。
考虑一个等价类中,走到第一行/列的方案数如何算?首先将等价类所有的入口(等价类外边,往左/上走一步可以到达等价类内部)找出来,设他们是 \((a_i,b_i,f_i)\),\(f_i\) 表示 dp 值,然后 \(a,b\) 是这个点到右上角的距离。
对于到第一行的,然后设个 GF:

\[\sum \frac{\mathsf{occ}^{b_i}\times x^{a_i}\times f_i}{(1-\mathsf{occ}\times x)^{b_i+1}} \]

由于 \(a_i,b_i\) 同增,可以分治计算。列同理,总复杂度 \(O(n\log ^2 n)\)。

UOJ697 【候选队互测2022】广为人知题

将问题放到二维平面,这是一个二维数点问题。
对于同一个等价类内部的询问,我们可以直接二位数点处理。
对于外部的,可以差分成求:行/列的祖先和、右侧一个代表元的答案。
复杂度 \(1\log\)

posted @ 2025-12-30 18:48  TallBanana  阅读(46)  评论(0)    收藏  举报