bzoj 4503

没有权限号就只能对拍了

我们令?代表的T值=0,然后设出这样一个式子

这样一来,只要T和S在j位置匹配,当且仅当Dj=0,然后我们将这个式子拆开,变成下面那样

 

思路大概就是这样

最后发现答案应该是在ans[lens2-1]---------ans[lens1-1]之间的

翻转字符用FFT优化是一种常见策略

代码:

#include <bits/stdc++.h>
using namespace std;
#define dob complex<double>
const double pi = acos(-1.0);
const int N = 6e4*4;
int n, m, l, r[N+5], sum[N+5],ans[N+5];
dob a[N+5], b[N+5],a1[N+5],b1[N+5];
void fft(dob *a,int o)
{
    for (int i=0;i<n;i++)
      if (i>r[i]) swap(a[i],a[r[i]]);
    for (int i=1;i<n;i*=2)
    {
        dob wn(cos(pi/i),sin(pi*o/i)),x,y;
        for (int j=0;j<n;j+=(i*2))
        {
            dob w(1,0);
            for (int k=0;k<i;k++,w*=wn)
            {
                x=a[j+k]; y=w*a[i+j+k];
                a[j+k]=x+y,a[i+j+k]=x-y;
            }
        }
    }
}
char s1[N],s2[N];
void query()
{
    l=0;
    for (n = 1; n <= m; n <<= 1) l++;
    for (int i=0;i<n;i++) r[i]=(r[i/2]/2)|((i&1)<<(l-1));
    fft(a,1),
    fft(b,1);
    for (int i=0;i<n;i++) a[i]*=b[i];
    fft(a,-1);
    for (int i=0;i<=m;i++) sum[i]=int (a[i].real()/n+0.5); 
}
void clearr()
{
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    memset(sum,0,sizeof(sum));
}
int main()
{
    freopen("noip.in","r",stdin);
    freopen("noip.out","w",stdout);
    ios::sync_with_stdio(false); 
    cin>>s1>>s2;
    for (int i=0;i<strlen(s1);i++)
      a1[strlen(s1)-i-1]=s1[i]-' ';
    for (int i=0;i<strlen(s2);i++)
      if (s2[i]=='?') b[i]=0;
      else b1[i]=s2[i]-' ';
    n=max(strlen(s1),strlen(s2)); n--; m=n*2;
    clearr();
    for (int i=0;i<strlen(s1);i++)
      a[i]=a1[i]*a1[i];
    for (int i=0;i<strlen(s2);i++)
      b[i]=b1[i];
//    cout<<b1[0].real();
//    cout<<a1[0].real()<<" "<<a[0].real()<<endl;
    query();
    for (int i=0;i<=m;i++) ans[i]+=sum[i];
    clearr();
//    cout<<b1[0].real();
    for (int i=0;i<strlen(s1);i++)
      a[i]=a1[i];
    for (int i=0;i<strlen(s2);i++)
      b[i]=b1[i]*b1[i];
    query();
    for (int i=0;i<=m;i++) ans[i]-=2*sum[i];
    int sum2=0;
    for (int i=0;i<strlen(s2);i++) 
      sum2+=pow(b1[i].real(),3);
    for (int i=0;i<=m;i++)
       ans[i]+=sum2;
    int ans1=0;
    for (int i=strlen(s2)-1;i<=strlen(s1)-1;i++)
      if (!ans[i]) ans1++;
    cout<<ans1<<endl;
}

 

posted @ 2018-03-07 00:53  尹吴潇  阅读(194)  评论(0编辑  收藏  举报