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;
    }
    
    
    


  • 相关阅读:
    Leetcode 16.25 LRU缓存 哈希表与双向链表的组合
    Leetcode437 路径总和 III 双递归与前缀和
    leetcode 0404 二叉树检查平衡性 DFS
    Leetcode 1219 黄金矿工 暴力回溯
    Leetcode1218 最长定差子序列 哈希表优化DP
    Leetcode 91 解码方法
    Leetcode 129 求根到叶子节点数字之和 DFS优化
    Leetcode 125 验证回文串 双指针
    Docker安装Mysql记录
    vmware虚拟机---Liunx配置静态IP
  • 原文地址:https://www.cnblogs.com/thythy/p/5493575.html
Copyright © 2011-2022 走看看