bzoj4259

fft

搞一个生成函数

对于每位A(j)=Σi=1->m (a[i]-b[i+j])^2*a[i]*b[i+j]

如果A(j)=0说明这位匹配

如果这位是*那么a[i]=0否则等于字母-'a'+1,b也是这样构造

然后我们翻转a串就可以加速了

#include<bits/stdc++.h>
using namespace std;
#define pi acos(-1)
const int N = (1 << 20) + 5;
int n = 1, n1, n2, k;
char s1[N], s2[N];
int t[N], ans[N];
struct data {
    double a, b;
    data() { a = 0; b = 0; }
    data(double _, double __) : a(_), b(__) {}
    data friend operator + (const data &a, const data &b) { return data(a.a + b.a, a.b + b.b); }
    data friend operator - (const data &a, const data &b) { return data(a.a - b.a, a.b - b.b); }
    data friend operator * (const data &a, const data &b) { return data(a.a * b.a - a.b * b.b, a.a * b.b + a.b * b.a); }
} a0[N], b0[N], a1[N], b1[N], a2[N], b2[N];
void fft(data *a, int f)
{
    for(int i = 0; i < n; ++i) 
    {
        int t = 0;
        for(int j = 0; j < k; ++j) if(i >> j & 1) t |= 1 << (k - j - 1);
        if(i < t) swap(a[i], a[t]); 
    }
    for(int l = 2; l <= n; l <<= 1) 
    {
        int m = l >> 1;
        data w = data(cos(pi / m), f * sin(pi / m));
        for(int i = 0; i < n; i += l) 
        {
            data t = data(1, 0);
            for(int k = 0; k < m; ++k, t = t * w)
            {
                data x = a[i + k], y = t * a[i + k + m];
                a[i + k] = x + y;
                a[i + k + m] = x - y;
            }
        }
    }
}
int main()
{
    scanf("%d%d%s%s", &n1, &n2, s1, s2);
    reverse(s1, s1 + n1);
    --n1;
    --n2;
    for(int i = 0; i <= n1; ++i) if(s1[i] != '*') 
    {
        double x = s1[i] - 'a' + 1;
        a0[i] = data(x, 0);
        a1[i] = data(x * x, 0);
        a2[i] = data(x * x * x, 0);
    }    
    for(int i = 0; i <= n2; ++i) if(s2[i] != '*') 
    {
        double x = s2[i] - 'a' + 1;
        b0[i] = data(x, 0);
        b1[i] = data(-2 * x * x, 0); 
        b2[i] = data(x * x * x, 0);
    }    
    while(n <= n1 + n2) n <<= 1, ++k; 
    fft(a0, 1);
    fft(a1, 1);
    fft(a2, 1);
    fft(b0, 1);
    fft(b1, 1);
    fft(b2, 1);
    for(int i = 0; i < n; ++i) a2[i] = a2[i] * b0[i], a1[i] = a1[i] * b1[i], a0[i] = a0[i] * b2[i], a2[i] = a2[i] + a1[i] + a0[i];
    fft(a2, -1);
    for(int i = 0; i < n; ++i) t[i] = (int)(a2[i].a / n + 0.1);
    for(int i = 0; i <= n2 - n1; ++i) if(t[i + n1] == 0) ans[++ans[0]] = i + 1;
    printf("%d\n", ans[0]);
    for(int i = 1; i < ans[0]; ++i) printf("%d ", ans[i]);
    printf("%d\n", ans[ans[0]]);
    return 0;
}
View Code

 

posted @ 2017-12-15 15:42  19992147  阅读(74)  评论(0编辑  收藏  举报