題意:定義*號可匹配任意字符。給出A串,B串,求A串在B中完全匹配的所有位置。
將*號視作0,則兩個等長的串可匹配當且僅當Σ(a[i]-b[i])^2*a[i]*b[i]==0。將A串和B串最左邊對齊,每次上式都要重算一次,不科學。所以講A串先反轉過來然後補上*號,就是卷積啦。
原來的萬徑人蹤滅一題當中用FFT來求了迴文串,這裏又能玩字符串匹配,真是太6了。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define clr(a) memset(a,0,sizeof a)
#define DB double
const int MAXN = 300005;
const int MAXL = MAXN*4;
int N, M;
const DB PI = acos(-1);
struct cpx
{
DB r, i;
cpx() {}
cpx(DB a, DB b):r(a), i(b){};
inline cpx operator + (cpx b) { return cpx(r+b.r, i+b.i); }
inline cpx operator - (cpx b) { return cpx(r-b.r, i-b.i); }
inline cpx operator * (cpx b) { return cpx(r*b.r - i*b.i, r*b.i+i*b.r); }
};
namespace FFT
{
int r[MAXL], L;
cpx a[MAXL], b[MAXL];
void fft(cpx*a, int flag, int N)
{
rep(i, 0, N-1) if (i<r[i]) swap(a[i], a[r[i]]);
for (int i = 1; i<N; i<<=1)
{
cpx wn(cos(PI/i), flag*sin(PI/i));
for (int j = 0; j<N; j+=i<<1)
{
cpx w(1, 0);
for (int k = 0; k<i; ++k, w=w*wn)
{
cpx x = a[j+k], y = w*a[j+k+i];
a[j+k] = x+y, a[j+k+i] = x-y;
}
}
}
if (flag<0) rep(i, 0, N-1) a[i].r /= N;
}
void mul(DB*pol1, DB*pol2, int N, int M)
{
rep(i, 0, N) a[i] = cpx(pol1[i], 0);
rep(i, 0, M) b[i] = cpx(pol2[i], 0);
int tn = N+1, tm = M+1; r[0] = 0;
for (M+=N, L=0, N=1; N<=M; N<<=1) ++L;
rep(i, tn, N) a[i] = cpx(0, 0);
rep(i, tm, N) b[i] = cpx(0, 0);
rep(i, 0, N) r[i] = (r[i>>1]>>1)|((i&1)<<(L-1));
fft(a, 1, N); fft(b, 1, N);
rep(i, 0, N) a[i] = a[i]*b[i];
fft(a, -1, N);
rep(i, 0, M) pol1[i] = a[i].r;
}
}
char A[MAXN], B[MAXN];
DB p1[MAXN*2], p2[MAXN*2], f[MAXN];
int an, ans[MAXN];
int main()
{
scanf("%d%d", &N, &M);
scanf("%s%s", A, B);
reverse(A, A+N);
rep(i, 0, N-1)
{
if (A[i] == '*') A[i] = 0;
else A[i] -= 'a'-1;
}
rep(i, 0, M-1)
{
if (B[i] == '*') B[i] = 0;
else B[i] -= 'a'-1;
}
rep(i, 0, N-1) p1[i] = 1.0*A[i]*A[i]*A[i];
rep(i, 0, M-1) p2[i] = B[i];
FFT::mul(p1, p2, N-1, M-1);
rep(i, 0, M-1) f[i] += p1[i];
rep(i, 0, N-1) p1[i] = 1.0*A[i]*A[i];
rep(i, 0, M-1) p2[i] = 1.0*B[i]*B[i];
FFT::mul(p1, p2, N-1, M-1);
rep(i, 0, M-1) f[i] -= 2*p1[i];
rep(i, 0, N-1) p1[i] = A[i];
rep(i, 0, M-1) p2[i] = 1.0*B[i]*B[i]*B[i];
FFT::mul(p1, p2, N-1, M-1);
rep(i, 0, M-1) f[i] += p1[i];
rep(i, N-1, M-1) if (int(f[i]+0.2)==0) ans[++an] = i+1-(N-1);
printf("%d\n", an);
rep(i, 1, an) printf("%d%c", ans[i], i!=an?' ':'\n');
return 0;
}