题解只给了code,能不能解释一下这到底是在做什么以及这样做为什么是对的?
翻译如下:(机翻)
首先,考虑解决方案而不考虑计算量。
考虑一个具有N个顶点的图形。当Si=Sj时,在顶点i和j之间连接一条蓝色边;当Si=Sj时,在顶点i和j之间连接一条红色边。
首先,对于每个i,根据(Si−Ai,Si−Ai+1,…,Si+Ai)构成回文串的条件,添加蓝色边(i−Ai,i+Ai),(i−Ai+1,i+Ai−1),…,(i−1,i+1)。
接下来,对于每个i,如果2≤i−Ai,i+Ai≤N−1,则需要满足(Si−Ai−1,Si−Ai+1,…,Si+Ai+1)不构成回文串的条件,即Si−Ai−1=Si+Ai+1。因此,在顶点i−Ai−1和i+Ai+1之间添加红色边(i−Ai−1,i+Ai+1)。
蓝色边连接的连通分量中的顶点必须取相同的值。因此,缩减蓝色边连接的连通分量。然后,在每个连通分量中,按照红色边两端的顶点取不同的值,即可求得解。
缩减连通分量后,若存在由红色边构成的自环,则无法给连通分量赋值满足条件的S。
若不存在由红色边构成的自环,则从包含较小编号顶点的连通分量开始,贪心地依次给尚未使用的较小值赋予相邻连通分量,直到所有值被分配为止。
以上解法的问题在于蓝色边的最大数量为O(N2)。因此,必须在保持蓝色边的连通性的前提下,减少必须连接的蓝色边的数量。
通过应用Manacher算法,可以将蓝色边的数量减少至O(N)。Manacher算法是一种在O(N)时间内计算给定字符串的以每个索引为中心的最大回文子串长度的算法。
Manacher算法的核心思想是“利用已经计算过的信息,省略已知构成回文的部分的计算”。有关算法的详细解释请参见以下文献:
通过应用Manacher算法,当存在满足条件的S时,可以通过以下伪代码正确地构建蓝色边。
在此,注意A的索引和顶点编号从0开始计数。此外,函数unite(u, v)用于在顶点u,v之间添加蓝色边。
分析该算法的时间复杂度。乍看之下,由于存在双重循环,似乎为O(N2)。实际上,我们将证明它实际上是O(N)的。
首先,分析第3行的while循环while j < A[i] + 1的执行次数。注意i+j的值,
因此,第3行的while循环最多执行大约N次。
其次,分析第8行的while循环while i - k >= 0 and k + A[i - k] + 1 < j的执行次数。考虑i的值,
因此,第8行的while循环最多执行大约N次。
综上所述,可以确认该算法在O(N)时间内运行。
以上算法实际上是在“当存在满足条件的S时”条件下运行的。因此,必须检查得到的S实际上是否满足条件。通过再次使用Manacher算法,可以在O(N)时间内进行此检查。