萬徑人蹤滅 HYSBZ - 3160
阿新 • • 發佈:2018-12-28
求不連續迴文子序列數量。
首先FFT求迴文子序列數量,再用manachar算出連續迴文子串數量。
完了。。。。。。
#define maxn 300005 #define LL long long #define mod 1000000007 using namespace std; const double Pi = 3.1415926535897932384626433832795; int n,lgn,f[maxn]; char s[maxn]; struct cplx { double r,i; cplx(double r=0,double i=0):r(r),i(i){} cplx operator +(const cplx &B)const{ return cplx(r+B.r,i+B.i); } cplx operator -(const cplx &B)const{ return cplx(r-B.r,i-B.i); } cplx operator *(const cplx &B)const{ return cplx(r*B.r-i*B.i,r*B.i+i*B.r); } cplx conj(){ return cplx(r,-i); } }A[maxn],w[maxn]={1},B[maxn]; int r[maxn]; inline void FFT(cplx A[maxn],int lgn,int tp) { int n = 1<<lgn; for(int i=0;i<n;i++) if(i < r[i]) swap(A[i],A[r[i]]); for(int L=2;L<=n;L<<=1) { int l = L>>1;w[1] = cplx(cos(Pi/l),sin(Pi/l)*tp); for(int i=2;i<l;i++) w[i] = w[i-1] * w[1]; for(int st=0;st<n;st+=L) for(int k=0;k<l;k++) { cplx tmp = w[k] * A[st+k+l]; A[st+k+l] = A[st+k] - tmp , A[st+k] = A[st+k] + tmp; } } if(tp==-1) for(int i=0;i<n;i++) A[i].r/=n; } inline int Pow(int base,int k) { int ret = 1; for(;k;k>>=1,base=1ll*base*base%mod) if(k&1) ret=1ll*ret*base%mod; return ret; } inline int manachar() { static char ns[maxn]={}; int tot = 0; ns[++tot] = '$'; for(int i=0;i<n;i++) ns[++tot] = '*' , ns[++tot] = s[i]; ns[++tot] = '*', ns[++tot] = '&'; static int len[maxn] = {}; int mx=0,o=0,ans=0; for(int i=0;i<tot;i++) { if(i<mx) len[i] = min(len[2*o-i],mx-i); else len[i]=1; for(;ns[i-len[i]]==ns[i+len[i]];len[i]++); if(i+len[i] > mx) mx = i + len[i] , o = i; ans = (ans + len[i]/2) % mod; } return ans; } int main() { scanf("%s",s); n = strlen(s); for(lgn=0;2*n>=(1<<lgn);lgn++); for(int i=0,len=1<<lgn;i<len;i++) r[i] = (r[i>>1]>>1) + ((i&1)<<(lgn-1)); for(int i=0;i<n;i++) if(s[i] == 'a') A[i].r=1; FFT(A,lgn,1); for(int i=0,len=1<<lgn;i<len;i++) B[i] = A[i] * A[i]; FFT(B,lgn,-1); for(int i=0;i<2*n;i++) f[i] += int(B[i].r+1.5)/2; memset(A,0,sizeof A); for(int i=0;i<n;i++) if(s[i] == 'b') A[i].r=1; FFT(A,lgn,1); for(int i=0,len=1<<lgn;i<len;i++)B[i]=A[i]*A[i]; FFT(B,lgn,-1); int ans = 0; for(int i=0;i<2*n;i++) { f[i] += int(B[i].r+1.5)/2; } for(int i=0;i<2*n;i++) { f[i] = Pow(2,f[i]) - 1; ans = (f[i] + ans) % mod; } printf("%d\n",(ans - manachar()+mod)%mod); }