BZOJ 4259: 残缺的字符串

Description

有通配符的字符串匹配.\(n,m\leqslant 3\times 10^5\)

Solution

FFT.

跟上题差不多,不过S也有通配符,那么再加一个S进去就行了...

\(D_k=\sum_{i+j=k}(S_i-T_j)^2S_iT_j\)

被卡常了qwq...

Code

/**************************************************************
    Problem: 4259
    User: BeiYu
    Language: C++
    Result: Accepted
    Time:7640 ms
    Memory:67924 kb
****************************************************************/
 
#include <bits/stdc++.h>
using namespace std;
 
typedef long long LL;
const int N = 1100500;
const double Pi = M_PI;
 
namespace Pol {
    struct cp {
        double x,y;
        cp(double _x=0,double _y=0) :x(_x),y(_y) {};
    };
    cp operator + (const cp &a,const cp &b) { return cp(a.x+b.x,a.y+b.y); }
    cp operator - (const cp &a,const cp &b) { return cp(a.x-b.x,a.y-b.y); }
    cp operator * (const cp &a,const cp &b) { return cp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x); }
     
    int pn;
    int rev[N];
    void init(int n) {
        for(pn=1;pn<=n;pn<<=1);
        for(int i=0,j=0;i<pn;i++) {
            rev[i]=j;
            for(int k=pn>>1;(j^=k)<k;k>>=1);
        }
    }
    void Rev(cp a[],int n=pn) {
        for(int i=0;i<n;i++) if(rev[i]>i) swap(a[i],a[rev[i]]);
    }
    void DFT(cp a[],int r=1,int n=pn) {
        Rev(a);
        for(int i=2;i<=n;i<<=1) {
            cp wi=cp(cos(2*Pi/i),r*sin(2*Pi/i));
            for(int j=0;j<n;j+=i) {
                cp w=cp(1,0);
                for(int k=j;k<j+i/2;k++) {
                    cp t1=a[k],t2=w*a[k+i/2];
                    a[k]=t1+t2,a[k+i/2]=t1-t2;
                    w=w*wi;
                }
            }
        }if(!~r) for(int i=0;i<n;i++) a[i].x/=n;
    }
    void FFT(cp a[],cp b[],cp c[],int n=pn) {
        DFT(a,1,n),DFT(b,1,n);
        for(int i=0;i<n;i++) c[i]=a[i]*b[i];
        DFT(c,-1,n);
    }
}
 
using namespace Pol;
int n,m;
char s[N],t[N];
double a[N],b[N];
LL st[N];
cp ss[N],tt[N];
 
int main() {
    scanf("%d%d",&m,&n);
    scanf("%s%s",t,s);
    n=strlen(s),m=strlen(t);
    reverse(t,t+m);
    init(n+m);
    for(int i=0;i<n;i++) a[i]=s[i]=='*'?0:s[i]-'a'+1;
    for(int i=0;i<m;i++) b[i]=t[i]=='*'?0:t[i]-'a'+1;
     
    memset(ss,0,sizeof(ss)),memset(tt,0,sizeof(tt));
    for(int i=0;i<pn;i++) ss[i].x=a[i]*a[i]*a[i],tt[i].x=b[i];
    FFT(ss,tt,ss);
    for(int i=0;i<pn;i++) st[i]+=(LL)(ss[i].x+0.5);
     
    memset(ss,0,sizeof(ss)),memset(tt,0,sizeof(tt));
    for(int i=0;i<pn;i++) ss[i].x=a[i]*a[i],tt[i].x=b[i]*b[i];
    FFT(ss,tt,ss);
    for(int i=0;i<pn;i++) st[i]-=2*(LL)(ss[i].x+0.5);
     
    memset(ss,0,sizeof(ss)),memset(tt,0,sizeof(tt));
    for(int i=0;i<pn;i++) ss[i].x=a[i],tt[i].x=b[i]*b[i]*b[i];
    FFT(ss,tt,ss);
    for(int i=0;i<pn;i++) st[i]+=(LL)(ss[i].x+0.5);
     
    int ans=0;
    for(int i=m-1;i<n;i++) if(st[i]==0) ans++;
    printf("%d\n",ans);
    for(int i=m-1;i<n;i++) if(st[i]==0) printf("%d ",i-m+1+1);
    return 0;
}

  

 

posted @ 2017-04-17 16:22  北北北北屿  阅读(161)  评论(0编辑  收藏  举报