考虑枚举对称轴 i (如果对称轴在原串第 x 个字符则对称轴为 2x ,如果在第 x 和第 x+1 个字符之间则为 2x+1 )
如果有 k对字符关于对称轴 i 对称,则可以为答案贡献 2k (实际上可能不是 2k ,注意空串、恰好在对称轴上的字符等细节)
考虑求 ki 表示以 i 为对称轴,满足 j+k=i 且原串第 j 和第 k 个字符相同的有序二元组 (j,k) 个数
把字符 a 和字符 b 分开处理
定义序列 A 的第 i 个元素表示原串第 i 个字符是否为 a ,是则为 1 ,否则为 0
序列 B 的第 i 个元素表示原串第 i 个字符是否为 b ,是则为 1 ,否则为 0
那么
ki=j+k=i∑([A[j]=1,A[k]=1]+[B[j]=1,B[k]=1])
=j=0∑i(A[j]×A[i−j]+B[j]×B[i−j])
是一个卷积的形式
直接上 FFT , O(nlogn)
然后去掉字符为连续一段的方案数
将原串用无关字符隔开之后, Manacher 求回文半径,设为 r[]
最后统计答案时,对于一个 i∈[2,2n]
如果 i 为奇数(对称轴在两个字符之间)时为答案贡献
2⌊2ki⌋−⌊2ri⌋
否则 i 为偶数(对称轴为一个字符),为答案贡献
2⌊2ki⌋+1−⌊2ri⌋−1
复杂度 O(nlogn)
Code
#include<bits/stdc++.h>#define For(i, a, b) for (i = a; i <= b; i++)#define Pow(k, n) for (k = 1; k < n; k <<= 1)#define Step(i, a, b, x) for (i = a; i <= b; i += x)typedef std::complex<double> cplx;template<classT>
T Min(T a, T b){return a < b ? a : b;}template<classT>voidSwap(T &a, T &b){T t = a; a = b; b = t;}constint N =1e5+5, M = N <<1, L =3e5+5, ZZQ =1e9+7;constdouble pi =acos(-1.0);int n, m, r[M], rev[L], ff =1, tot =0, ans, p2[N], ansa[M], ansb[M];char s[N], t[M];
cplx a[L], b[L];voidmanacher(){int i, mx =0, pos =0;
For (i,1, m){
r[i]= mx > i ?Min(r[(pos <<1)- i], mx - i):1;while(t[i - r[i]]== t[i + r[i]]) r[i]++;if(i + r[i]> mx) mx = i + r[i], pos = i;}}voidFFT(int n, cplx *a,int op){int i, j, k;
For (i,0, n -1)if(i < rev[i])Swap(a[i], a[rev[i]]);Pow(k, n){
cplx x(cos(pi / k),sin(pi / k)* op);
Step (i,0, n -1, k <<1){
cplx w(1,0);
For (j,0, k -1){
cplx u = a[i + j], v = w * a[i + j + k];
a[i + j]= u + v;
a[i + j + k]= u - v;
w *= x;}}}}intmain(){int i;scanf("%s", s +1);
n =strlen(s +1);
p2[0]=1;
For (i,1, n) p2[i]=2* p2[i -1]% ZZQ;
t[0]='%'; t[m =1]='#';
For (i,1, n) t[++m]= s[i], t[++m]='#';
t[m +1]='^';
For (i,1, n)if(s[i]=='a') a[i]=1, b[i]=0;else a[i]=0, b[i]=1;while(ff <=(n <<1)) ff <<=1, tot++;manacher();
For (i,0, ff -1)
rev[i]=(rev[i >>1]>>1)|((i &1)<< tot -1);FFT(ff, a,1);FFT(ff, b,1);
For (i,0, ff -1) a[i]*= a[i], b[i]*= b[i];FFT(ff, a,-1);FFT(ff, b,-1);
For (i,0, ff -1) a[i]/= ff, b[i]/= ff;
For (i,2, m -1) ansa[i]= a[i].real()+0.5,
ansb[i]= b[i].real()+0.5;
For (i,2, m -1)if(i &1) ans =(ans +(p2[(ansa[i]>>1)+(ansb[i]>>1)]-1-(r[i]>>1)+ ZZQ)% ZZQ)% ZZQ;else ans =(((ans + p2[(ansa[i]>>1)+(ansb[i]>>1)])% ZZQ -(r[i]>>1)+ ZZQ)% ZZQ
+ p2[(ansa[i]>>1)+(ansb[i]>>1)]-1)% ZZQ;
std::cout << ans << std::endl;return0;}