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

    残缺的字符串

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 1327  Solved: 300
    [Submit][Status][Discuss]

    Description

    很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n。可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同程度的残缺。
    你想对这两个串重新进行匹配,其中A为模板串,那么现在问题来了,请回答,对于B的每一个位置i,从这个位置开始连续m个字符形成的子串是否可能与A串完全匹配?
     

    Input

    第一行包含两个正整数m,n(1<=m<=n<=300000),分别表示A串和B串的长度。
    第二行为一个长度为m的字符串A。
    第三行为一个长度为n的字符串B。
    两个串均仅由小写字母和*号组成,其中*号表示相应位置已经残缺。
     

    Output

    第一行包含一个整数k,表示B串中可以完全匹配A串的位置个数。
    若k>0,则第二行输出k个正整数,从小到大依次输出每个可以匹配的开头位置(下标从1开始)。
     

    Sample Input

    3 7
    a*b
    aebr*ob

    Sample Output

    2
    1 5

    HINT

     

    Source

    [Submit][Status][Discuss]


    HOME Back


    题解:其实和两个串差不多,就是第一个有了通配符,第二个有了通配符。

       然后第二个翻转卷积就ok了。

      

     1 #include<cstring>
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<cmath>
     6 
     7 #define ll long long
     8 #define N 1<<20
     9 #define pi acos(-1)
    10 using namespace std;
    11 inline int read()
    12 {
    13     int x=0,f=1;char ch=getchar();
    14     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    15     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    16     return x*f;
    17 }
    18 
    19 int n,m,hjq,res,num,L;
    20 int c[N],d[N],rev[N];
    21 char ch[N];
    22 
    23 struct comp
    24 {
    25     double r,v;
    26     comp(){r=v=0.0;}
    27     comp(double a,double b){r=a,v=b;}
    28     friend inline comp operator+(comp x,comp y){return comp(x.r+y.r,x.v+y.v);}
    29     friend inline comp operator-(comp x,comp y){return comp(x.r-y.r,x.v-y.v);}
    30     friend inline comp operator*(comp x,comp y){return comp(x.r*y.r-x.v*y.v,x.r*y.v+x.v*y.r);}
    31 }a1[N],b1[N],a2[N],b2[N],a3[N],b3[N],fzy[N];
    32 
    33 void FFT(comp *a,int flag)
    34 {
    35     for (int i=0;i<num;i++)
    36         if (i<rev[i]) swap(a[i],a[rev[i]]);
    37     for (int i=1;i<num;i<<=1)
    38     {
    39         comp wn=comp(cos(pi/i),flag*sin(pi/i));
    40         for (int j=0;j<num;j+=(i<<1))
    41         {
    42             comp w=comp(1,0);
    43             for (int k=0;k<i;k++,w=w*wn)
    44             {
    45                 comp x=a[j+k],y=w*a[j+k+i];
    46                 a[j+k]=x+y,a[j+k+i]=x-y;
    47             }
    48         }
    49     }
    50     if (flag==-1) for (int i=0;i<num;i++) a[i].r/=num; 
    51 }
    52 int main()
    53 {
    54     m=read(),n=read();
    55     scanf("%s",ch);for (int i=0;i<m;i++) d[i]=(ch[m-i-1]=='*')?0:ch[m-i-1]-'a'+1;
    56     scanf("%s",ch);for (int i=0;i<n;i++) c[i]=(ch[i]=='*')?0:ch[i]-'a'+1;
    57     
    58     for (num=1;num<=n+m-1;num<<=1,L++);if (L) L--;
    59     for (int i=0;i<num;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<L);
    60     
    61     for (int i=0;i<n;i++) a1[i].r=c[i]*c[i]*c[i];
    62     for (int i=0;i<m;i++) b1[i].r=d[i];
    63     for (int i=0;i<n;i++) a2[i].r=-2*c[i]*c[i];
    64     for (int i=0;i<m;i++) b2[i].r=d[i]*d[i];
    65     for (int i=0;i<n;i++) a3[i].r=c[i];
    66     for (int i=0;i<m;i++) b3[i].r=d[i]*d[i]*d[i];
    67     
    68     FFT(a1,1),FFT(b1,1),FFT(a2,1),FFT(b2,1),FFT(a3,1),FFT(b3,1);
    69     for (int i=0;i<num;i++) fzy[i]=a1[i]*b1[i]+a2[i]*b2[i]+a3[i]*b3[i];
    70     FFT(fzy,-1);
    71 
    72     for (int i=m-1;i<n;i++) if (!(ll)(fzy[i].r+0.5)) res++;
    73     printf("%d
    ",res);
    74     for (int i=m-1;i<n;i++)
    75         if (!(ll)(fzy[i].r+0.5)) printf("%d ",i-m+2);
    76 }
  • 相关阅读:
    INNODB在裸设备上的性能简单测试
    java interface 不能存常量数组?
    jfreechart linux图片中文显示乱码解决方法
    linux下tomcat工程从oracle读取中文出现乱码
    java读取文件输出流出现的问题
    运用mysqldump 工具时注意的问题
    ibatis中字段名问题
    oracle 定长字段查询问题 ,ibatis 与pl/sql查询的char类型字段查询不同
    ibatis #跟$的区别
    C#取整相关
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8681994.html
Copyright © 2011-2022 走看看