zoukankan      html  css  js  c++  java
  • BZOJ 3160 FFT+Manacher

    思路:
    这道题思路好奇怪…….

    我们先要知道关于x (x可以是间隙) 对称的有几对字母
    显然暴力是n^2的
    那怎么办呢

    先把所有’a’看成1 ‘b’看成0

    意外的发现 这不就是卷积嘛

    再倒过来搞一搞
    加一下

    2^x-1就是包含连续的回文串的解了

    然后 跑个manacher 把包含的删掉就好啦

    时间复杂度是O(nlogn)的

    代码:

    //By SiriusRen
    #include <cstdio>
    #include <complex>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    typedef complex<double> cplxd;
    const int N=270050,mod=1000000007;const double pi=acos(-1);
    int n,nn,L,R[N],p[N],id,mx,ans;
    char ch[N];
    cplxd a[N],b[N];
    void FFT(cplxd *a,int f){
        for(int i=0;i<n;i++)if(i<R[i])swap(a[i],a[R[i]]);
        for(int i=1;i<n;i<<=1){
            cplxd wn(cos(pi/i),f*sin(pi/i));
            for(int j=0;j<n;j+=(i<<1)){
                cplxd w(1,0);
                for(int k=0;k<i;k++,w*=wn){
                    cplxd x=a[j+k],y=w*a[j+k+i];
                    a[j+k]=x+y,a[j+k+i]=x-y;
                }
            }
        }
        if(!~f)for(int i=0;i<n;i++)a[i]/=n;
    }
    int pow(ll x){
        ll res=1,tmp=2;
        for(;x;x>>=1,tmp=(tmp*tmp)%mod)if(x&1)res=(res*tmp)%mod;
        return res;
    }
    int main(){
        scanf("%s",ch+1);
        n=strlen(ch+1),nn=n*2+2;
        for(int i=1;i<=n;i++)if(ch[i]=='a')a[i]=1;else b[i]=1;
        for(int i=n;i;i--)ch[i*2]=ch[i],ch[i*2-1]='#';
        ch[0]='&',ch[n*2+1]='#',ch[n*2+2]='$';
        for(n=1;n<=nn;n<<=1)L++;
        for(int i=0;i<n;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
        FFT(a,1);for(int i=0;i<n;i++)a[i]*=a[i];FFT(a,-1);
        FFT(b,1);for(int i=0;i<n;i++)b[i]*=b[i];FFT(b,-1);
        for(int i=0;i<n;i++)a[i]+=b[i];
        for(int i=1;i<=nn;i++){
            if(mx>i)p[i]=min(p[id*2-i],p[id]+id-i);
            else p[i]=1;
            while(ch[i-p[i]]==ch[i+p[i]])p[i]++;
            if(i+p[i]>mx)mx=i+p[i],id=i;
        }
        for(int i=1;i<=nn;i++,ans%=mod)ans-=(p[i]-(i&1))/2;
        for(int i=0;i<n;i++)ans=(ans+pow((ll(a[i].real()+1.1))/2)-1)%mod;
        printf("%d
    ",ans);
    }

    这里写图片描述

  • 相关阅读:
    SoapUI 使用笔记
    git 使用笔记(二)
    git 使用笔记(一)
    jquery 拓展
    hdu 1024 Max Sum Plus Plus (DP)
    hdu 2602 Bone Collector (01背包)
    hdu 1688 Sightseeing (最短路径)
    hdu 3191 How Many Paths Are There (次短路径数)
    hdu 2722 Here We Go(relians) Again (最短路径)
    hdu 1596 find the safest road (最短路径)
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/6532061.html
Copyright © 2011-2022 走看看