BZOJ 4259: 残缺的字符串

好久之前写的题,过来贴一下:

i = 0 n 1 ( a [ i ] b [ i ] ) 2 a [ i ] b [ i ]

设为 0 ,则只有上面那个式子等于 0 时才是完全匹配的。

a b ( a b ) 2 = a 3 b 2 a 2 b 2 + a b 3

因此可以三次FFT,然后判断每一项是否为 0 即可。

    for (int i = 0; i < la; ++i) {
        if (aa[la-i-1] == '*') a[i].x = 0;
        else a[i].x = aa[la-i-1] - 96;
    }
    for (int i = 0; i < lb; ++i) {
        if (bb[i] == '*') b[i].x = 0;
        else b[i].x = bb[i] - 96;
    }
    FFT(a, 1), FFT(b, 1);
    for (int i = 0; i < n; ++i) {
        c[0][i] = a[i] * a[i] * a[i] * b[i];
        c[1][i] = a[i] * a[i] * b[i] * b[i];
        c[2][i] = a[i] * b[i] * b[i] * b[i];
    }
    FFT(c[0], -1), FFT(c[1], -1), FFT(c[2], -1);

这样写是错的。因为每一个 i 都对应着含有 x 的一项,这样就成了多个多项式的卷积,而不是两个,导致不能控制匹配的地方指数相等了。

所以要先把 a 乘在一起, b 乘在一起,得到两个多项式再卷积。

for (int i = 0; i < n; ++i) a[i] = Complex(0, 0), b[i] = Complex(0, 0);

注意这里必须清零到 n

26 6 会爆 i n t ,所以要开 l o n g   l o n g d o u b l e 也可以)

#include <cstdio>
#include <cmath>
#include <algorithm>

typedef long long ll;
const int N = 1048576+5, M = 300005;
const double PI = acos(-1.0);

ll ans[M<<1];
int n, m, L, R[N], la, lb, f[M], g[M], sta[M], top;
char aa[M], bb[M];

struct Complex {
    double x, y; Complex() {}
    Complex(double a, double b) : x(a), y(b) {}
    Complex operator + (const Complex &r) { return Complex(x + r.x, y + r.y); }
    Complex operator - (const Complex &r) { return Complex(x - r.x, y - r.y); }
    Complex operator * (const Complex &r) { return Complex(x * r.x - y * r.y, x * r.y + y * r.x); }
} a[N], b[N];

void FFT(Complex *A, int f) {
    for (int i = 0; i < n; ++i) if (i < R[i]) std::swap(A[i], A[R[i]]);
    for (int i = 1; i < n; i <<= 1) {
        Complex wn(cos(PI/i), f*sin(PI/i));
        int r = i << 1;
        for (int j = 0; j < n; j += r) {
            Complex w(1, 0);
            for (int k = 0; k < i; ++k, w = w * wn) {
                Complex x = A[j+k], y = w * A[i+j+k];
                A[j+k] = x + y, A[i+j+k] = x - y;
            }
        }
    }
}
void calc(int nn, int mm) {
    for (int i = 0; i < n; ++i) a[i] = Complex(0, 0), b[i] = Complex(0, 0);
    for (int i = 0; i < la; ++i) {
        a[i].x = 1;
        for (int j = 1; j <= nn; ++j) a[i].x *= f[i];
    }
    for (int i = 0; i < lb; ++i) {
        b[i].x = 1;
        for (int j = 1; j <= mm; ++j) b[i].x *= g[i];
    }
    FFT(a, 1), FFT(b, 1);
    for (int i = 0; i < n; ++i) a[i] = a[i] * b[i];
    FFT(a, -1);
    for (int i = 0; i <= m; ++i) {
        if (nn != 2) ans[i] += (ll)(a[i].x / n + 0.5);
        else ans[i] -= (ll)(a[i].x / n + 0.5) << 1;
    }
}

int main() {
    scanf("%d%d", &n, &m); scanf("%s%s", aa, bb);
    la = n, lb = m, m += n; for (n = 1; n <= m; n <<= 1) ++L;
    for (int i = 0; i < n; ++i) R[i] = (R[i>>1] >> 1) | ((i & 1) << (L - 1));
    for (int i = 0; i < la; ++i) if (aa[i] != '*') f[la-i-1] = aa[i] - 96;
    for (int i = 0; i < lb; ++i) if (bb[i] != '*') g[i] = bb[i] - 96;

    calc(1, 3), calc(2, 2), calc(3, 1);

    for (int i = la - 1; i <= lb - 1; ++i)
        if (ans[i] == 0) sta[++top] = i - la + 2;
    printf("%d\n", top);
    for (int i = 1; i <= top; ++i) printf("%d ", sta[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Milkyyyyy/article/details/81147039
今日推荐