zoukankan      html  css  js  c++  java
  • bzoj 4259: 残缺的字符串

    神啊,FFT真是无所不能。

    可以这么想吧:

    我们高(处)中(小学)老师教过我们判定2个东西是不是相等的方法,一个是做差等于0,一个是相除等于1,这个题就是用的做差等于0

    所以现在对于每一位,做差即(ai-bi)而且现在有一些可以随意匹配,那就意味着这一位就直接是0,所以随后我们就是求一段和全为0的东西,

    也就是 ∑(ai-bi)*ai*bi==0这个东西我们发现还是怪怪的,所以把一个串翻转,变成 ∑(aj-bi)*aj*bi==0(i+j是常数),哈!!233这不就是卷积嘛!

    直接FFT就好,然后判段某一位是不是0就行了

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cmath>
     4 #include <cstring>
     5 #define pi acos(-1)
     6 using namespace std;
     7 
     8 const int maxn=600005; 
     9 
    10 struct complex
    11 {
    12     double r,i;
    13     complex (double a=0, double b=0) {r=a; i=b;}
    14     complex operator + (const complex a) {return complex(r+a.r,i+a.i);}
    15     complex operator - (const complex a) {return complex(r-a.r,i-a.i);}
    16     complex operator * (const complex a) {return complex(r*a.r-i*a.i,r*a.i+i*a.r);}
    17 }A[maxn<<1],B[maxn<<1],ans[maxn<<1];
    18 
    19 int N,n,m,cnt,Ans[maxn],a[maxn],b[maxn],rev[maxn];
    20 char s[maxn],t[maxn];
    21 
    22 void FFT(complex *a, int f)
    23 {
    24     for (int i=0; i<N; i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
    25     for (int h=2; h<=N; h<<=1)
    26     {
    27         complex wn(cos(2*pi*f/h),sin(2*pi*f/h));
    28         for (int i=0; i<N; i+=h)
    29         {
    30             complex w(1,0);
    31             for (int j=0; j<(h>>1); j++,w=w*wn)
    32             {
    33                 complex x=a[i+j],y=w*a[i+j+(h>>1)];
    34                 a[i+j]=x+y;
    35                 a[i+j+(h>>1)]=x-y;
    36             }
    37         }
    38     }
    39     if (f==-1) for (int i=0; i<N; i++) a[i].r/=(double)N;
    40 }
    41 
    42 int main(int argc, char const *argv[])
    43 {
    44     scanf("%d%d",&m,&n); 
    45     scanf("%s",s); scanf("%s",t);
    46     for (int i=0; i<m; i++) a[i]=(s[m-i-1]=='*')?0:s[m-i-1]-'a'+1;
    47     for (int i=0; i<n; i++) b[i]=(t[i]=='*')?0:t[i]-'a'+1;
    48     int L=0;
    49     for (N=1; N<(n+m); N<<=1) L++;
    50     for (int i=0; i<N; i++)    rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
    51 
    52     for (int i=0; i<m; i++) A[i]=a[i]*a[i]*a[i];
    53     for (int i=0; i<n; i++) B[i]=b[i];
    54     FFT(A,1); FFT(B,1);
    55     for (int i=0; i<N; i++) ans[i]=A[i]*B[i];
    56 
    57     memset(A,0,sizeof(A)); memset(B,0,sizeof(B));
    58     for (int i=0; i<m; i++) A[i]=a[i];
    59     for (int i=0; i<n; i++) B[i]=b[i]*b[i]*b[i];
    60     FFT(A,1); FFT(B,1);
    61     for (int i=0; i<N; i++) ans[i]=ans[i]+A[i]*B[i];
    62 
    63     memset(A,0,sizeof(A)); memset(B,0,sizeof(B));
    64     for (int i=0; i<m; i++) A[i]=2*a[i]*a[i];
    65     for (int i=0; i<n; i++) B[i]=b[i]*b[i];
    66     FFT(A,1); FFT(B,1);
    67     for (int i=0; i<N; i++) ans[i]=ans[i]-A[i]*B[i];
    68     
    69     FFT(ans,-1);
    70     for (int i=m-1; i<n; i++) if (ans[i].r<0.1 && ans[i].r>-0.1) Ans[++cnt]=i-m+2;
    71     printf("%d
    ",cnt);
    72     for (int i=1; i<=cnt; i++) printf("%d ",Ans[i]);
    73     return 0;
    74 }
  • 相关阅读:
    SQL2005四个排名函数(row_number、rank、dense_rank和ntile)的比较
    LINQ to List泛型的几种简单查询
    sql语句精选
    C#利用QrCode.Net生成二维码(Qr码)
    LINQ to XML CRUD,并且封装为DAL方法
    vim编辑器
    去年的烟花特别多……
    年初七
    活死人黎明 Dawn of the Dead
    在碟片里奔驰我的看碟人生
  • 原文地址:https://www.cnblogs.com/ccd2333/p/6733769.html
Copyright © 2011-2022 走看看