做题记录 25.9.25

\(\textcolor{black}\odot\) P3785 [SDOI2017] 文本校正

假设将 \(t\) 划分为 $1$2$3 三部分,则组合 \(s\)\(6\) 种情况:$1,$2,$3$1,$3,$2$2,$1,$3$2,$3,$1$3,$1,$2$3,$2,$1

$1,$2,$3 的处理是显然的

$1,$3,$2$2,$1,$3$2,$3,$1$3,$1,$2 分别对称,以下只考虑 $2,$1,$3$2,$3,$1 的情况

231

等价于两者循环同构且位移长度超过 \(1\)(实际上位移为 \(1\) 时可以转化为 $3,$1,$2 的情况),可以用 sa 做到 \(O(n\log n)\)\(O(n)\)

另一种 \(O(n)\) 的实现:实际上就是对每个 \(i\) 判断是否有 \(t[1:i]=s[n-i+1:n]\)\(t[i+1:n]=s[1:n-i]\),对 \(ts\)\(st\)(表示拼接)分别求出 \(z\) 函数即可 \(O(1)\) 判定,该方法比 \(O(n)\) \(sa\)\(O(n)-O(1)\) \(rmq\) 常数小

213

等价于一个前缀循环同构,同样求出 \(ts\)\(st\)\(z\) 函数 \(z_{ts}[1\sim 2n]\)\(z_{st}[1\sim 2n]\),则需要找到一组 \((a,b)\) 使得 \(t[1:a]=t[b+1:b+a],t[a+1:a+b]=t[1:b],s[a+b+1:n]=s[a+b+1:n]\),令 \(p=\text{lcs}(t,s)\),等价于 \(a\ge 1,b\ge 1,a+b<n,a+b\ge n-p,z_{ts}[n+b+1]\ge a,z_{st}[n+a+1]\ge b\)

显然为二维数点的形式,容易树状数组做到 \(O(n\log n)\)

\(O(n)\) 方法:

枚举 \(a+b=i(n-p\le i<n)\),则 \(b\)\(s\) 的前缀和 \(t[1:i]\) 的后缀,求出 \(t\)\(\text{fail}\) 树,用 \(s\) 匹配 \(t\),则合法的 \(b\)\(\text{fail}\) 树上 \(i\) 的父亲到根(不含根)的链上的全体点

\(b\) 的限制为 \(b\le z_{st}[n+a+1]\)\(z_{ts}[n+b+1]\ge a\iff z_{ts}[n+b+1]+b\ge a+b=i\),即在 \(b\le z_{st}[n+a+1]\) 的情况下 \(z_{ts}[n+b+1]+b\) 尽量大,而 \(b\)\(\text{fail}\) 树上的直链已经保证了 \(b\le z_{st}[n+a+1]\) 满足,因此取 \(b\) 为直链上 \(z_{ts}[n+b+1]+b\) 最大的位置最优

显然这一过程可做到 \(O(n)\)

321

翻转 \(s\),和 \(t\) 交错排列,则转化为给定一个长度 \(2n\) 的串,判定能否划分为恰好三个长度为偶数的非空回文子串,以下用 \(s\) 表示这一字符串,以下回文都表示长度为偶数且回文

先跑一遍 \(\text{manacher}\) 对每个回文中心求出最大回文半径

定理:对于一个 \(s[1:n]\)\(1\le a<b<c<n\),令 \(la=s[1:a],ra=s[a+1:n]\)\(lb=s[1:b],rb=s[b+1:n]\)\(lc=s[1:c],rc=s[c+1:n]\),若 \(ra,lb,rb,lc\) 回文,则 \(la\)\(rc\) 也回文

证明:

  • +----+----------+
    | la |   *ra*   |
    +----+-+--------+
    | *lb* |  *rb*  |
    +----------+----+
    | *lc*     | rc |
    +----------+----+
         ->| v |<-
    
  • \(v=lc\cap rb\)
  • \(v\)\(rb\) 的前缀,为 \(rb^R\) 的前缀,为 \(ra^R\) 的前缀,为 \(ra\) 的前缀
  • 因此 \(la \cdot v\)\(la\cdot ra\) 的前缀,为 \(lc\) 的前缀
  • 由于 \(lb\)\(lc\)\(\text{border}\),因此 \(v\)\(lc\) 的周期
  • 因此 \(la\)\(v^{+\infty}\) 的后缀
  • \(v^R\)\(lc\) 的前缀,因此 \(la\)\((v^R)^{+\infty}\) 的前缀,即 \(la^R\)\(v^{+\infty}\) 的后缀
  • 因此 \(la=la^R\)\(la\) 回文
  • 同理得到 \(rc\) 回文

由此容易得到:对于一个 \(i\),若 \([1,i]\) 回文,则只需要考虑 \([1,i],[i+1,j],[j+1,n]\)(其中 \(j\) 为第一个满足 \(j>i\)\([j+1,n]\) 回文的位置)和 \([1,i],[i+1,k],[k+1,n]\)(其中 \(k\) 为最后一个满足 \([i+1,j]\) 回文的位置),该判定过程容易做到 \(O(n)\)

代码 (代码中 st 互换)

参考 1

参考 2

\(\textcolor{purple}\odot\) CF547E Mike and Friends

每个区间询问拆为两个前缀之差,考虑如何计算 \(s_p\)\(s_{1\sim i}\) 中的出现次数

离线,将询问挂在 \(i\)

先用 \(s_{1\sim n}\) 建立 \(\text{ACAM}\)

\(1\)\(n\) 扫描,枚举到 \(s_i\) 时,用 \(s_i\)\(\text{ACAM}\) 上跑,对于每个访问到的点 \(k\),令 \(\text{fail}\) 树上 \(k\) 到根的链答案加一,\(s_i\) 处的询问直接单点查询

链加单点查询转化为单点加区间查询,树状数组即可

时间复杂度 \(O(m|\sum|+(q+m)\log m)\),其中 \(m=\sum|s_i|\)

代码

参考

\(\textcolor{black}\odot\) P13665 「TPOI-5D」「僕は…」

一次查询 \((l,r,L,R)\) 中,将 \([l,r]\) 分块,整块部分每块建立 \(\text{ACAM}\),令 \(c_u\) 表示结点 \(u\) 到根的链上终止位置数量,扫描 \(i=1\sim n\),用 \(s_i\)\(\text{ACAM}\) 上跑,并累加上跑到的点的 \(c\) 之和,散块部分使用 \(\textcolor{purple}\odot\) CF547E Mike and Friends 的方式,将树状数组改为 \(O(\sqrt m)\) 加,\(O(1)\) 查询的分块,即可做到总时间复杂度 \(O(m|\sum|+m\sqrt m+\frac{(m+q)n}S+qS)\),假定 \(n,m,q\) 同阶则时间复杂度 \(O(n\sqrt n+n|\sum|)\),离线后依次处理每一块可做到空间线性

卡常提示:

  1. 整块部分统计答案时不必将询问挂到 \(L-1\)\(R\) 处,直接枚举询问判断,可以显著提升速度
  2. \(O(\sqrt m)\)\(O(1)\) 查询的分块尽量减少数组,实际只需要维护到块左端点的和与块的前缀和两个数组即可
  3. 块长取 \(500\) 左右足够通过,也许可以继续优化
  4. 不要让数组退化为指针,这样会丢失对齐信息从而影响 \(\text{simd}\) 优化

代码

参考

\(\textcolor{black}\odot\) CF587F Duff is Mad

\(\textcolor{black}\odot\) P13665 「TPOI-5D」「僕は…」 弱化版

代码

QOJ #5311. Master of Both

考虑预处理 \(c_{x,y}=\sum_{1\le i<j\le n}[s_{i,\text{lcp}(i,j)+1}=x][s_{j,\text{lcp}(i,j)+1}=y]\),则可 \(O(|\sum|^2)\) 回答一组询问

将字符串依次插入 \(\text{Trie}\),每次插入时计算贡献即可 \(O(m|\sum|)\),其中 \(m=\sum|s_i|\),注意特殊处理字符串有前缀关系时的贡献

总时间复杂度 \(O(m|\sum|+ q|\sum|^2)\),容易优化到 \(O((m+q)|\sum|)\)

代码

参考

posted @ 2025-09-26 07:26  Hstry  阅读(8)  评论(0)    收藏  举报