好久之前写的题,过来贴一下:
将 设为 ,则只有上面那个式子等于 时才是完全匹配的。
而
因此可以三次FFT,然后判断每一项是否为 即可。
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);
这样写是错的。因为每一个 都对应着含有 的一项,这样就成了多个多项式的卷积,而不是两个,导致不能控制匹配的地方指数相等了。
所以要先把 乘在一起, 乘在一起,得到两个多项式再卷积。
for (int i = 0; i < n; ++i) a[i] = Complex(0, 0), b[i] = Complex(0, 0);
注意这里必须清零到
会爆 ,所以要开 ( 也可以)
#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;
}