http://www.elijahqi.win/archives/3096
题目在上方链接
Description
Input
Output
Sample Input
Sample Output
HINT
Source
2013湖北互测week1
首先将字符串中间插入”#” 把他们分隔开
题目要求求不连续的回文串的个数 那么就用总数减去连续的即可 考虑连续的部分 直接用manacher求即可 算出长度 然后再/2就是答案
不连续的怎么办 考虑现在用#将他们隔开 然后假如只考虑字符是a的贡献
那么 显然字符a都会出现在偶数位置上 那么想办法知道一个位置左右对称的符合要求的字符即可得到答案 比如#a#b#a这样关于b左右对称的就是2 然后答案就是2^2-1
那么想办法计算出左右对称位置符合要求的这个t即可
设当前在第k位
f[k]=∑i不越界[k−imod2=0][sk−i=′a′][sk+i=′a′] f [ k ] = ∑ i 不 越 界 [ k − i mod 2 = 0 ] [ s k − i = ′ a ′ ] [ s k + i = ′ a ′ ] ∑t∑i不越界[k−i=2×t][sk−i2=′a′][sk+i2=′a′] ∑ t ∑ i 不 越 界 [ k − i = 2 × t ] [ s k − i 2 = ′ a ′ ] [ s k + i 2 = ′ a ′ ] ∑t∑i不越界[k−i=2×t]st∗sk−t ∑ t ∑ i 不 越 界 [ k − i = 2 × t ] s t ∗ s k − t ∑t[k−2∗t>=0]st∗sk−t ∑ t [ k − 2 ∗ t >= 0 ] s t ∗ s k − t ∑t=0⌊k2⌋st∗sk−t ∑ t = 0 ⌊ k 2 ⌋ s t ∗ s k − t s即表示该串这个位置是否为a|b为的话就是1
然后两次dft一次idft即可
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define pi acos(-1)
#define ll long long
using namespace std;
const int mod=1000000007;
const int N=100020;
struct C{
double a,b;
inline friend C operator +(const C &x,const C &y){return (C){x.a+y.a,x.b+y.b};}
inline friend C operator -(const C &x,const C &y){return (C){x.a-y.a,x.b-y.b};}
inline friend C operator *(const C &x,const C &y){return (C){x.a*y.a-x.b*y.b,x.a*y.b+x.b*y.a};}
inline void operator *=(const C &y){*this=*this*y;}
}a[N<<2],b[N<<2];
int n,m,R[N<<2],p[N<<1];ll ans;
inline void fft(C *x,int f){
for (int i=0;i<n;++i) if (i<R[i]) swap(x[i],x[R[i]]);
for (int i=1;i<n;i<<=1){
C wn=(C){cos(pi/i),f*sin(pi/i)};
for (int j=0;j<n;j+=i<<1){
C w=(C){1,0},t1,t2;
for (int k=0;k<i;++k,w*=wn)
t1=x[j+k],t2=x[j+k+i]*w,x[j+k]=t1+t2,x[j+k+i]=t1-t2;
}
}if (f==-1) for (int i=0;i<n;++i) x[i].a/=n;
}
inline int ksm(ll b,int t){static ll tmp;tmp=1;
for (;t;b=b*b%mod,t>>=1) if (t&1) tmp=tmp*b%mod;return tmp;
}char s[N],s1[N<<1];
template<class T>
inline void add(T &x,int v){x=x+v>=mod?x+v-mod:x+v;}
template<class T>
inline void dec(T &x,int v){x=x-v<0?x-v+mod:x-v;}
int main(){
freopen("bzoj3160.in","r",stdin);
scanf("%s",s+1);m=strlen(s+1);m<<=1;
int t=0;for (n=1;n<=m;n<<=1,++t);m>>=1;
for (int i=0;i<n;++i) R[i]=(R[i>>1]>>1)|((i&1)<<t-1);
for (int i=1;i<=m;++i) a[i].a=s[i]=='a',b[i].a=s[i]=='b';
fft(a,1);
// for (int i=0;i<n;++i) printf("%f\n",a[i].a);
fft(b,1);for (int i=0;i<n;++i) a[i]=a[i]*a[i],b[i]=b[i]*b[i],a[i]=a[i]+b[i];
fft(a,-1);for (int i=1;i<=m;++i) s1[i*2-1]='#',s1[i<<1]=s[i];m<<=1;int mx=0,id=0;
for (int i=2;i<=m;++i) add(ans,ksm(2,((int)(a[i].a+0.1)+1>>1))-1);s1[++m]='#';
// for (int i=1;i<=m;++i) printf("%lf\n",a[i].a);
// for (int i=2;i<=m;++i) printf("%d\n",(int)(a[i].a+0.1)>>1);
for (int i=1;i<=m;++i){
if (i<mx) p[i]=min(mx-i,p[(id<<1)-i]);else p[i]=1;
while(i-p[i]>0&&i+p[i]<=m&&s1[i-p[i]]==s1[i+p[i]]) ++p[i];
if(i+p[i]>mx) mx=i+p[i],id=i;dec(ans,p[i]>>1);
}
// for (int i=1;i<=m;++i) printf("%d ",p[i]);
printf("%lld\n",ans);
return 0;
}