P2375 [NOI2014] 动物园

题意:

定义\(num[i]\)为一个序列前\(i\)位不重叠公共前后缀的个数,给定序列,对于每一个\(i\)\(num[i]\)

解法:

先不考虑前后缀重不重叠的问题,那么当且仅当\(next[i]\)\(next[next[i]]\)\(next[next[next[i]]]......\)是这个前缀串\(i\)的公共前后缀。
如何去除有重叠的?

首先显然\(next[i] < i\)

也就是说,一旦有一个递归了\(n\)层的\(next\),比原前缀\(i\)的长度的一半要小,那么这个\(next\)的递推出的答案\(ans\)就是\(i\)\(num\)

一个问题
假如我们拿到的串是1e6个'a',那么上面那个算法就会被卡成\(O(n^2)\)

那么我们需要做一个优化,来解决这个问题,而解决问题的核心就是:减少重复递归

如同求\(next\)时一样的方法,我们将递归用的变量j的值不更新,这样,求完了i的答案以后,\(j\)的位置一定在$ i / 2$
的左边,也就是它已经满足要求了,再递归求解

posted @ 2023-07-27 14:45  星河倒注  阅读(15)  评论(0)    收藏  举报