zoukankan      html  css  js  c++  java
  • BZOJ3160: 万径人踪灭(FFT,回文自动机)

    BZOJ传送门:

    解题思路:

    FFT在处理卷积时可以将自己与自己卷,在某一种字母上标1其他标0,做字符集次就好了。

    (回文就是直接对称可以联系偶函数定义理解,根据这个性质就可以将字符串反向实现字符串匹配)。

    最后利用容斥回文字符2的次幂-回文串就好了。

    回文串计数当然要回文自动机了。

    代码:

      1 #include<cmath>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 typedef long long lnt;
      6 const int maxn=362144;
      7 const double PI=acos(-1.0);
      8 const lnt mod=(lnt)(1e9+7);
      9 struct cp{
     10     double x,y;
     11     cp(){};
     12     cp(double a,double b){x=a,y=b;}
     13     cp friend operator + (cp a,cp b){return cp(a.x+b.x,a.y+b.y);}
     14     cp friend operator - (cp a,cp b){return cp(a.x-b.x,a.y-b.y);}
     15     cp friend operator * (cp a,cp b){return cp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
     16 }A[maxn],B[maxn],C[maxn];
     17 struct PAM{
     18     struct pant{
     19         int tranc[2];
     20         int len;
     21         int pre;
     22         int wgt;
     23     }h[maxn];
     24     int siz;
     25     int fin;
     26     lnt ans;
     27     bool mis(char *a,int i,int lsp)
     28     {
     29         return a[i]!=a[i-h[lsp].len-1];
     30     }
     31     void Insert(char *a,int i)
     32     {
     33         int nwp,lsp,mac;
     34         lsp=fin;
     35         int c=a[i]-'a';
     36         while(mis(a,i,lsp))
     37             lsp=h[lsp].pre;
     38         if(!h[lsp].tranc[c])
     39         {
     40             nwp=++siz;
     41             mac=h[lsp].pre;
     42             h[nwp].len=h[lsp].len+2;
     43             while(mis(a,i,mac))
     44                 mac=h[mac].pre;
     45             h[nwp].pre=h[mac].tranc[c];
     46             h[lsp].tranc[c]=nwp;
     47             h[nwp].wgt=h[h[nwp].pre].wgt+1;
     48         }
     49         fin=h[lsp].tranc[c];
     50         ans+=h[fin].wgt;
     51         return ;
     52     }
     53     PAM(){}
     54     PAM(char *a,int n)
     55     {
     56         ans=0;
     57         siz=1;
     58         fin=0;
     59         h[1].pre=h[0].pre=1;
     60         h[1].len=-1;
     61         h[0].len=0;
     62         for(int i=1;i<=n;i++)
     63             Insert(a,i);
     64     }
     65     lnt val(void)
     66     {
     67         return ans;
     68     }
     69 };
     70 int lim;
     71 int len;
     72 int n,m;
     73 int pos[maxn];
     74 lnt pow2[maxn];
     75 char str[maxn];
     76 void getpos(void)
     77 {
     78     for(int i=0;i<len;i++)
     79         pos[i]=(pos[i>>1]>>1)|((i&1)<<(lim-1));
     80     return ;
     81 }
     82 void Fft(cp *a,double flag)
     83 {
     84     for(int i=0;i<len;i++)
     85         if(i<pos[i])
     86             std::swap(a[i],a[pos[i]]);
     87     for(int i=2;i<=len;i<<=1)
     88     {
     89         cp wn(cos(2.00*PI*flag/(double)(i)),sin(2.00*PI*flag/(double)(i)));
     90         for(int j=0;j<len;j+=i)
     91         {
     92             cp w(1.00,0.00),t;
     93             for(int k=0;k<(i>>1);k++,w=w*wn)
     94             {
     95                 t=a[k+j+(i>>1)]*w;
     96                 a[j+k+(i>>1)]=a[j+k]-t;
     97                 a[j+k]=a[j+k]+t;
     98             }
     99         }
    100     }
    101     return ;
    102 }
    103 int main()
    104 {
    105     scanf("%s",str+1);
    106     int lth=strlen(str+1);
    107     for(int i=1;i<=lth;i++)
    108         if(str[i]=='a')
    109             A[i-1].x=1.00;
    110         else
    111             B[i-1].x=1.00;
    112     while((1<<lim)<(lth<<1))
    113         lim++;
    114     len=1<<lim;
    115     getpos();
    116     Fft(A,1);
    117     Fft(B,1);
    118     for(int i=0;i<len;i++)
    119         A[i]=A[i]*A[i]+B[i]*B[i];
    120     Fft(A,-1);
    121     pow2[0]=1;
    122     for(int i=1;i<=len;i++)
    123         pow2[i]=pow2[i-1]*2ll%mod;
    124     lnt ans=0;
    125     for(int i=0;i<len;i++)
    126         ans=(ans+pow2[((lnt)(A[i].x/(double)(len)+0.5)+1ll)/2]-1ll)%mod;
    127     PAM P(str,lth);    
    128         ans=((ans-P.val())%mod+mod)%mod;
    129     printf("%lld
    ",ans);
    130     return 0;
    131 }   
  • 相关阅读:
    命令行标签
    ts关键还是js 因为要编译成js
    nuxt axios
    vuecli3-ssr
    v-text
    这样竟然也可以水平居中 两个属性都必须
    纯CSS实现垂直居中的几种方法
    下图片异步变同步
    [Java] 扯淡系列_找工作流程 与 注意问题
    [Java] Spring3.0 Annotation
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10085150.html
Copyright © 2011-2022 走看看