zoukankan      html  css  js  c++  java
  • bzoj3160: 万径人踪灭

    题面传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3160


    思路:首先题目中不要连续的回文串,那么答案就是总的回文串-连续回文串

    连续回文串用manacher就可以O(n)搞出来

    现在的问题是求总的回文串。

    既然是回文串,我们就想到枚举对称轴

    为了方便表示在字符的夹缝的对称轴,下标*2,下标为奇数则为夹缝。

    令f[i]为对称轴为i时两边相同的字符对数,那么答案就是sigma (2^f[i])-1

    现在的问题是快速求f[i]

    令a[i]表示原串第i个为是否为a,b[i]表示原串第i个为是否为b;

    那么f[i]=sigma a[j]*a[k]+sigma b[x]+b[y] (j+k=i,x+y=i,j<=k,x<=y)

    这不就是卷积

    上FFT搞一搞就可以了

    被递归版代码常数吓傻,卡着时限A...

    #include<ctime>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    const int maxn=270010,mod=1000000007;
    const double pi=M_PI;
    using namespace std;
    struct plex{
        double r,i;
    }tmp[maxn];
     
    plex operator +(plex a,plex b){return (plex){a.r+b.r,a.i+b.i};}
    plex operator -(plex a,plex b){return (plex){a.r-b.r,a.i-b.i};}
    plex operator *(plex a,plex b){return (plex){a.r*b.r-a.i*b.i,a.r*b.i+a.i*b.r};}
     
    struct DFT{
        plex a[maxn];
        void fft(int bg,int step,int size,int op){
            if (size==1) return;
            fft(bg,step<<1,size>>1,op),fft(bg+step,step<<1,size>>1,op);
            plex w=(plex){1,0},t=(plex){cos(2*pi/size),sin(2*pi*op/size)};
            int p=bg,p0=bg,p1=bg+step;
            for (int i=0;i<size/2;i++){
                tmp[p]=a[p0]+w*a[p1];
                tmp[p+size/2*step]=a[p0]-w*a[p1];
                p+=step,p0+=step*2,p1+=step*2,w=w*t;
            }
            for (int i=bg;size;size--,i+=step) a[i]=tmp[i];
        }
    }a,b;
    int f[maxn<<1],len,n,nn,POW[maxn],ans;char str[maxn],s[maxn<<1];
     
    int manacher(){
        int i,res=0;
        for (s[0]='$',s[1]='#',i=1;i<=n;i++) s[i<<1]=str[i-1],s[(i<<1)|1]='#';
        n=(n<<1)|1;
        int mx=1,id=1;
        for (int i=1;i<=n;i++){
            f[i]=min(f[id+id-i],mx-i);
            for (;s[i+f[i]]==s[i-f[i]];) f[i]++;
            if (f[i]+i>mx) mx=f[i]+i,id=i;
            res+=f[i]>>1,res%=mod;
        }
        return res;
    }
     
    int main(){
        POW[0]=1;for (int i=1;i<maxn;i++) POW[i]=(POW[i-1]<<1)%mod;
        scanf("%s",str),n=strlen(str);
        for (nn=1;nn<(n<<1);nn<<=1);
        for (int i=0;i<n;i++) a.a[i].r=(str[i]=='a'?1.0:0.0);
        for (int i=0;i<n;i++) b.a[i].r=(str[i]=='b'?1.0:0.0);
        a.fft(0,1,nn,1),b.fft(0,1,nn,1);
        for (int i=0;i<nn;i++)
        	a.a[i]=a.a[i]*a.a[i]+b.a[i]*b.a[i];
        a.fft(0,1,nn,-1);
        for (int i=0;i<nn;i++) a.a[i].r/=nn;
        for (int i=0;i<nn;i++){
            int x=(int)(round(a.a[i].r)+1)>>1;
            ans=(ans+POW[x]-1)%mod;
        }
        //int t=(int)clock();
        printf("%d
    ",(ans-manacher()+mod)%mod);//
        //printf("%d
    ",(int)clock()-t);
        return 0;
    }
    
    
    


  • 相关阅读:
    G450 Ubuntu14 无线网卡解决
    USB设备不能用。提示Windows 无法启动这个硬件设备。 (代码 19)
    帮你选处理器:CPU T9500-p9500-T9400-T9300-p8700对比分析!
    全球各大运营商黑莓ROM官网下载链接汇总
    查看80端口被占用的方法(IIS、apmserv、system)
    Windows 2003 服务器安全设置-批处理 (附参考链接)
    解决Windows时间同步失败问题!系统时间同步设置!
    WinHTTP Web Proxy Auto-Discovery Service
    关于“未使用GUID分区表”无法安装的解决方案
    DataGridView使用技巧六:冻结列或行
  • 原文地址:https://www.cnblogs.com/thythy/p/5493575.html
Copyright © 2011-2022 走看看