• 洛谷P4173 残缺的字符串(FFT)


    传送门

    话说为什么字符串会和卷积扯上关系呢……到底得脑洞大到什么程度才能想到这种东西啊……大佬太珂怕了……

    因为通配符的关系,自动机已经废了

    那么换种方式考虑,如果两个字符串每一位对应的编码都相等,那么这两个字符串相等

    编码相等就代表$sum_{i=1}^na[i]-b[i]=0$

    然而这是不对的,有可能前面少一点,后面多一点,最好加起来还是$0$

    那就平方一下$sum_{i=1}^n(a[i]-b[i]=0)^2=0$,那就大丈夫了

    于是我们得到了比一位一位匹配更麻烦的方法

    看到平方……把它展开一下试试……结果……$sum_{i=1}^na[i]^2+b[i]^2-2a[i]b[i]$

    我们考虑把$b$给倒过来……这就是三个卷积啊!直接用FFT啊!加起来之后如果为$0$说明匹配上了

    然而……通配符怎么办……如果有一位有通配符,那么这一位代表的编码相减肯定是$0$了

    那么再改一下$sum_{i=1}^na[i]*b[i]*(a[i]-b[i])=0$,如果一个位置是通配符,就把$a[i]/b[i]$设为$0$

    然后就没有问题了……求一下卷积……如果第$i$位为$0$那么它就是一个能匹配上的字符串的结尾

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cmath>
     5 using namespace std;
     6 const int N=1100005;const double Pi=acos(-1.0);
     7 struct complex{
     8     double x,y;
     9     complex(double xx=0,double yy=0){x=xx,y=yy;}
    10     complex operator +(complex b){return complex(x+b.x,y+b.y);}
    11     complex operator -(complex b){return complex(x-b.x,y-b.y);}
    12     complex operator *(complex b){return complex(x*b.x-y*b.y,x*b.y+y*b.x);}
    13 }A[N],B[N],C[N];
    14 int n,m,l,r[N],limit=1;double a[N],b[N];
    15 void FFT(complex *A,int type){
    16     for(int i=0;i<limit;++i)
    17     if(i<r[i]) swap(A[i],A[r[i]]);
    18     for(int mid=1;mid<limit;mid<<=1){
    19         complex Wn(cos(Pi/mid),type*sin(Pi/mid));
    20         for(int R=mid<<1,j=0;j<limit;j+=R){
    21             complex w(1,0);
    22             for(int k=0;k<mid;++k,w=w*Wn){
    23                 complex x=A[j+k],y=w*A[j+mid+k];
    24                 A[j+k]=x+y,A[j+mid+k]=x-y;
    25             }
    26         }
    27     }
    28     if(type==-1)
    29     for(int i=0;i<limit;++i) A[i]=(int)(A[i].x/limit+0.5);
    30 }
    31 char s1[300005],s2[300005];int l1,l2,ans[N],res=0;
    32 int main(){
    33 //    freopen("testdata.in","r",stdin);
    34     scanf("%d%d",&l2,&l1);
    35     scanf("%s%s",s2,s1);
    36     m=l1+l2;
    37     while(limit<=m) limit<<=1,++l;
    38     for(int i=0;i<limit;++i)
    39     r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
    40     for(int i=0;i<l1;++i)
    41     a[i]=s1[i]=='*'?0:s1[i]-'a'+1;
    42     for(int i=0;i<l2;++i)
    43     b[l2-i-1]=s2[i]=='*'?0:s2[i]-'a'+1;
    44     for(int i=0;i<l1;++i) A[i].x=a[i]*a[i]*a[i];
    45     for(int i=0;i<l2;++i) B[i].x=b[i];
    46     FFT(A,1),FFT(B,1);
    47     for(int i=0;i<limit;++i) C[i]=A[i]*B[i];//a^3*b
    48     for(int i=0;i<limit;++i) A[i].x=a[i]*a[i],A[i].y=0;
    49     for(int i=0;i<limit;++i) B[i].x=b[i]*b[i],B[i].y=0;
    50     FFT(A,1),FFT(B,1);
    51     complex tmp(2,0);
    52     for(int i=0;i<limit;++i) C[i]=C[i]-A[i]*B[i]*tmp;//-2ab*a*b
    53     for(int i=0;i<limit;++i) A[i].x=a[i],A[i].y=0;
    54     for(int i=0;i<limit;++i) B[i].x=b[i]*b[i]*b[i],B[i].y=0;
    55     FFT(A,1),FFT(B,1);
    56     for(int i=0;i<limit;++i) C[i]=C[i]+A[i]*B[i];//b^3*a
    57     FFT(C,-1);
    58     for(int i=l2-1;i<l1;++i)
    59     if(C[i].x==0.0) ans[++res]=i-l2+2;
    60     printf("%d
    ",res);
    61     for(int i=1;i<=res;++i) printf("%d ",ans[i]);
    62     return 0;
    63 }
  • 相关阅读:
    【leetcode_easy_array】1450. Number of Students Doing Homework at a Given Time
    【leetcode_easy_array】1295. Find Numbers with Even Number of Digits
    【leetcode_easy_array】1266. Minimum Time Visiting All Points
    【leetcode_easy_array】1260. Shift 2D Grid
    【leetcode_easy_array】1275. Find Winner on a Tic Tac Toe Game
    【leetcode_easy_array】1450. Number of Students Doing Homework at a Given Time
    【leetcode_easy_array】1287. Element Appearing More Than 25% In Sorted Array
    【leetcode_easy_array】1299. Replace Elements with Greatest Element on Right Side
    【leetcode_easy_array】1512. Number of Good Pairs
    【leetcode_easy_array】1252. Cells with Odd Values in a Matrix
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9748340.html
Copyright © 2020-2023  润新知