题意
给出一个长度为偶数的字符串S,要求把S分成k部分,其中k为任意偶数,设为a[1..k],且满足对于任意的i,有a[i]=a[k-i+1]。问划分的方案数。
n<=1000000
分析
刚了一个下午的题,感觉学到了很多新东西。
首先直接做显然不可做,考虑把S变成S[1]S[n]S[2]S[n-1]…S[n/2]S[n/2+1]的形式,不难发现对于原来划分方案中的a[i]和a[k-i+1],它们在新串中恰好连续且组成一个回文串。那么问题就变成了把新串划分成若干部分,使得每一部分都是偶回文串,问方案。
一开始的想法是把回文树建出来,然后设f[i]表示把前i个字符划分的方案数,然后枚举i的每一个回文后缀进行转移。
这样子的复杂度是O(回文串数量)的,显然会超时,考虑如何优化。
有一个小结论就是一个回文串S的一个后缀T是回文串当且仅当T是S的border。
有一个性质就是一个串的所有border可以划分成O(log)段等差数列。
证明的话,可以考虑对于所有长度大于n/2的border,它们显然组成一个等差数列,然后把长度减半,如此类推,那么等差数列的数量就只有O(log)个。
对于回文树上的每个节点p,我们可以维护以它作为等差数列末项时每一项的f值之和g[p],维护nxt[p]表示节点p下一个等差数列的末项。
怎么维护呢?设当前节点为末项的等差数列有b1,b2,b3,其中b1>b2>b3。那么有g[p]=f[i-b1]+f[i-b2]+f[i-b3]。
根据回文串的性质,不难发现S[i-b2,i-d]=S[i