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$
的左边,也就是它已经满足要求了,再递归求解
在那高远的黑色穹顶之下,它的牺牲使圣巢永世不衰

浙公网安备 33010602011771号