bzoj 4503 两个串

Description

兔子们在玩两个串的游戏。给定两个字符串S和T,兔子们想知道T在S中出现了几次,
分别在哪些位置出现。注意T中可能有“?”字符,这个字符可以匹配任何字符。

Input

两行两个字符串,分别代表S和T

Output

第一行一个正整数k,表示T在S中出现了几次
接下来k行正整数,分别代表T每次在S中出现的开始位置。按照从小到大的顺序输出,S下标从0开始。

Sample Input

ababcadaca
a?a

Sample Output

3
0
5

HINT

S 长度不超过 10^5, T 长度不会超过 S。 S 中只包含小写字母, T中只包含小写字母和“?”

将b串反转

 设两个串的距离值为∑(ai-aj)2aiaj=∑ai3aj+∑aiaj3-∑2ai2aj2

当为*时ai为0

FFT直接上

#include<bits/stdc++.h>
#define pi acos(-1)
#define maxn 300010
using namespace std;
struct Complex{
    double r,i;
    Complex(double x=0,double y=0){r=x,i=y;}
    Complex operator + (Complex x){return Complex(r+x.r,i+x.i);}
    Complex operator - (Complex x){return Complex(r-x.r,i-x.i);}
    Complex operator * (Complex x){return Complex(r*x.r-i*x.i,r*x.i+i*x.r);}
}A[maxn],B[maxn],C[maxn];
char a[maxn],b[maxn];
int rev[maxn];
int N,L;
int k1[maxn],k2[maxn];
int l1,l2;
int ans;
int k[maxn];
void FFT(Complex a[],int n,int f){
    for(int i=0;i<n;++i)
        if(i<rev[i])
            swap(a[i],a[rev[i]]);
    for(int i=2;i<=n;i<<=1){
        Complex wn=Complex(cos(2*pi/i),sin(2*pi/i)*f);
        for(int j=0;j<n;j+=i){
            Complex w=Complex(1,0);
            for(int k=0;k<(i>>1);++k,w=w*wn){
                Complex tmp1=a[j+k],tmp2=a[j+k+(i>>1)]*w;
                a[j+k]=tmp1+tmp2;a[j+k+(i>>1)]=tmp1-tmp2;
            }
        }
    }
    if(f==-1)for(int i=0;i<n;++i)a[i].r/=n;
}
void init(){
    scanf("%s%s",a,b);
    l1=strlen(a);l2=strlen(b);
    for(int i=0;i<l1;++i)k1[i]=a[i]-'a'+1;
    for(int i=0;i<(l2>>1);++i)swap(b[i],b[l2-i-1]);
    for(int i=0;i<l2;++i)
        if(b[i]=='?')k2[i]=0;
        else k2[i]=b[i]-'a'+1;
    N=1,L=0;while(N<l1+l2)N<<=1,L++;
    for(int i=0;i<N;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
}
void work(){
    for(int i=0;i<N;++i)A[i]=Complex(k1[i],0);
    for(int i=0;i<N;++i)B[i]=Complex(k2[i]*k2[i]*k2[i],0);
    FFT(A,N,1);FFT(B,N,1);
    for(int i=0;i<N;++i)C[i]=C[i]+(A[i]*B[i]);
    for(int i=0;i<N;++i)A[i]=Complex(k1[i]*k1[i]*k1[i],0);
    for(int i=0;i<N;++i)B[i]=Complex(k2[i],0);
    FFT(A,N,1);FFT(B,N,1);
    for(int i=0;i<N;++i)C[i]=C[i]+(A[i]*B[i]);
    for(int i=0;i<N;++i)A[i]=Complex(k1[i]*k1[i]*2,0);
    for(int i=0;i<N;++i)B[i]=Complex(k2[i]*k2[i],0);
    FFT(A,N,1);FFT(B,N,1);
    for(int i=0;i<N;++i)C[i]=(C[i]-(A[i]*B[i]));
    FFT(C,N,-1);
    for(int i=l2-1;i<l1;++i)
        if(C[i].r<0.5)k[++ans]=i-l2+1;
    printf("%d\n",ans);
    for(int i=1;i<=ans;++i)
        printf("%d\n",k[i]);
}
int main(){
    init();
    work();
    return 0;
}
View Code

 

 

posted @ 2016-04-08 21:21  117208  阅读(285)  评论(0编辑  收藏  举报