关于 AtCoder ABC349 官方做法
  • 板块学术版
  • 楼主lnw143
  • 当前回复1
  • 已保存回复1
  • 发布时间2024/4/17 15:43
  • 上次更新2024/4/17 18:55:37
查看原帖
关于 AtCoder ABC349 官方做法
767819
lnw143楼主2024/4/17 15:43

题解只给了code,能不能解释一下这到底是在做什么以及这样做为什么是对的?

link

翻译如下:(机翻)


首先,考虑解决方案而不考虑计算量。

考虑一个具有NN个顶点的图形。当Si=SjS_i=S_j时,在顶点ii和jj之间连接一条蓝色边;当Si≠SjS_i\neq S_j时,在顶点ii和jj之间连接一条红色边。

首先,对于每个ii,根据(Si−Ai,Si−Ai+1,…,Si+Ai)(S_{i-A_i},S_{i-A_i+1},\dots,S_{i+A_i})构成回文串的条件,添加蓝色边(i−Ai,i+Ai),(i−Ai+1,i+Ai−1),…,(i−1,i+1)(i-A_i,i+A_i), (i-A_i+1,i+A_i-1), \dots, (i-1,i+1)。

接下来,对于每个ii,如果2≤i−Ai,i+Ai≤N−12\leq i-A_i,i+A_i\leq N-1,则需要满足(Si−Ai−1,Si−Ai+1,…,Si+Ai+1)(S_{i-A_i-1},S_{i-A_i+1},\dots,S_{i+A_i+1})不构成回文串的条件,即Si−Ai−1≠Si+Ai+1S_{i-A_i-1}\neq S_{i+A_i+1}。因此,在顶点i−Ai−1i-A_i-1和i+Ai+1i+A_i+1之间添加红色边(i−Ai−1,i+Ai+1)(i-A_i-1,i+A_i+1)。

蓝色边连接的连通分量中的顶点必须取相同的值。因此,缩减蓝色边连接的连通分量。然后,在每个连通分量中,按照红色边两端的顶点取不同的值,即可求得解。

缩减连通分量后,若存在由红色边构成的自环,则无法给连通分量赋值满足条件的SS。

若不存在由红色边构成的自环,则从包含较小编号顶点的连通分量开始,贪心地依次给尚未使用的较小值赋予相邻连通分量,直到所有值被分配为止。

以上解法的问题在于蓝色边的最大数量为O(N2)O(N^2)。因此,必须在保持蓝色边的连通性的前提下,减少必须连接的蓝色边的数量。

通过 Manacher 算法实现加速

通过应用Manacher算法,可以将蓝色边的数量减少至O(N)O(N)。Manacher算法是一种在O(N)O(N)时间内计算给定字符串的以每个索引为中心的最大回文子串长度的算法。

Manacher算法的核心思想是“利用已经计算过的信息,省略已知构成回文的部分的计算”。有关算法的详细解释请参见以下文献:

通过应用Manacher算法,当存在满足条件的SS时,可以通过以下伪代码正确地构建蓝色边。

在此,注意AA的索引和顶点编号从0开始计数。此外,函数unite(u, v)用于在顶点u,vu,v之间添加蓝色边。

分析该算法的时间复杂度。乍看之下,由于存在双重循环,似乎为O(N2)O(N^2)。实际上,我们将证明它实际上是O(N)O(N)的。

首先,分析第3行的while循环while j < A[i] + 1的执行次数。注意i+ji+j的值,

  • 考虑第10行和第11行,此时i+ji+j保持不变
  • i+ji+j只在第5行发生变化,每次变化递增1
  • 根据第3行的while循环条件,有i+j≤i+A[i]≤i+(N−i−1)<Ni+j \leq i+A[i] \leq i+(N-i-1) < N

因此,第3行的while循环最多执行大约NN次。

其次,分析第8行的while循环while i - k >= 0 and k + A[i - k] + 1 < j的执行次数。考虑ii的值,

  • kk是第8行while循环在该步骤中执行的次数
  • 由于ii是kk的总和,因此整个算法中第8行while循环执行的次数
  • 根据第2行while循环条件,有i<Ni < N

因此,第8行的while循环最多执行大约NN次。

综上所述,可以确认该算法在O(N)O(N)时间内运行。

以上算法实际上是在“当存在满足条件的SS时”条件下运行的。因此,必须检查得到的SS实际上是否满足条件。通过再次使用Manacher算法,可以在O(N)O(N)时间内进行此检查。

2024/4/17 15:43
加载中...