考虑枚举对称轴
i
i
i (如果对称轴在原串第
x
x
x 个字符则对称轴为
2
x
2x
2x ,如果在第
x
x
x 和第
x
+
1
x+1
x+1 个字符之间则为
2
x
+
1
2x+1
2x+1 )
如果有
k
k
k对字符关于对称轴
i
i
i 对称,则可以为答案贡献
2
k
2^k
2k (实际上可能不是
2
k
2^k
2k ,注意空串、恰好在对称轴上的字符等细节)
考虑求
k
i
k_i
ki 表示以
i
i
i 为对称轴,满足
j
+
k
=
i
j+k=i
j+k=i 且原串第
j
j
j 和第
k
k
k 个字符相同的有序二元组
(
j
,
k
)
(j,k)
(j,k) 个数
把字符
a
a
a 和字符
b
b
b 分开处理
定义序列
A
A
A 的第
i
i
i 个元素表示原串第
i
i
i 个字符是否为
a
a
a ,是则为
1
1
1 ,否则为
0
0
0
序列
B
B
B 的第
i
i
i 个元素表示原串第
i
i
i 个字符是否为
b
b
b ,是则为
1
1
1 ,否则为
0
0
0
那么
k
i
=
∑
j
+
k
=
i
(
[
A
[
j
]
=
1
,
A
[
k
]
=
1
]
+
[
B
[
j
]
=
1
,
B
[
k
]
=
1
]
)
k_i=\sum_{j+k=i}([A[j]=1,A[k]=1]+[B[j]=1,B[k]=1])
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
]
)
=\sum_{j=0}^i(A[j]\times A[i-j]+B[j]\times B[i-j])
=j=0∑i(A[j]×A[i−j]+B[j]×B[i−j])
是一个卷积的形式
直接上 FFT ,
O
(
n
log
n
)
O(n\log n)
O(nlogn)
然后去掉字符为连续一段的方案数
将原串用无关字符隔开之后, Manacher 求回文半径,设为
r
[
]
r[]
r[]
最后统计答案时,对于一个
i
∈
[
2
,
2
n
]
i\in[2,2n]
i∈[2,2n]
如果
i
i
i 为奇数(对称轴在两个字符之间)时为答案贡献
2
⌊
k
i
2
⌋
−
⌊
r
i
2
⌋
2^{\lfloor\frac{k_i}2\rfloor}-\lfloor\frac{r_i}2\rfloor
2⌊2ki⌋−⌊2ri⌋
否则
i
i
i 为偶数(对称轴为一个字符),为答案贡献
2
⌊
k
i
2
⌋
+
1
−
⌊
r
i
2
⌋
−
1
2^{\lfloor\frac{k_i}2\rfloor+1}-\lfloor\frac{r_i}2\rfloor-1
2⌊2ki⌋+1−⌊2ri⌋−1
复杂度
O
(
n
log
n
)
O(n\log n)
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;}