将s2串倒过来,把?看成0,
很容易把式子化成f[i] = ∑(s1[i] - s2[len2+i-j]))^2*s2[len2+i-j]
然后展开得到俩个卷积与一个常数,然后上fft即可
c++代码如下:
#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i = x ; i <= y;++ i)
typedef long long ll;
using namespace std;
template<typename T>inline void read(T&x)
{
x = 0;char c;int sign = 1;
do { c = getchar(); if(c == '-') sign = -1; }while(!isdigit(c));
do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c));
x *= sign;
}
const int g = 3,mod = 998244353,N = 4e5+500;
int R[N],len1,len2,n,m,L;
inline int quick_pow(int x,int y)
{
int ans = 1;
while(y)
{
if(y & 1) ans = 1ll * ans * x % mod;
x = 1ll * x * x % mod;
y >>= 1;
}
return ans;
}
inline void ntt(ll*a,int f)
{
rep(i,0,n - 1) if(i < R[i]) swap(a[i],a[R[i]]);
for(register int i = 1; i < n ; i <<= 1)
{
ll wn = quick_pow(g,(mod - 1)/(i << 1));
if(!(~f)) wn = quick_pow(wn,mod - 2);
for(register int j = 0; j < n ; j += (i << 1))
{
ll w = 1;
for(register int k = 0;k < i ;++k,w = w * wn % mod)
{
ll x = a[j + k],y = w * a[i + j + k] % mod;
a[j + k] = ((x + y) % mod + mod) % mod;
a[i + j + k] = ((x - y) % mod + mod) % mod;
}
}
}
if(f == -1)
{
int inv = quick_pow(n,mod - 2);
rep(i,0,n - 1) a[i] = a[i] * inv % mod;
}
}
char s1[N],s2[N];
ll a1[N],a2[N],b1[N],b2[N],sum,ans;
int main()
{
scanf("%s",s1);
scanf("%s",s2);
n = strlen(s1); m = strlen(s2);
len1 = n; len2 = m;
for(int i = 0,j = m - 1;i < j;++i,--j) swap(s2[i],s2[j]);
rep(i,0,n - 1) s1[i] = s1[i] - 'a' + 1;
rep(i,0,m - 1) s2[i] = s2[i] == '?'? 0 : s2[i] - 'a' + 1;
rep(i,0,m - 1) sum = sum + s2[i] * s2[i] * s2[i];
rep(i,0,n - 1) a1[i] = s1[i] * s1[i]; rep(i,0,n - 1) a2[i] = s1[i];
rep(i,0,m - 1) b1[i] = s2[i]; rep(i,0,m - 1) b2[i] = s2[i] * s2[i];
m = n + m - 2;
for(n = 1; n <= m ; n <<= 1,++L);
rep(i,0,n - 1) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1));
ntt(a1,1); ntt(a2,1); ntt(b1,1); ntt(b2,1);
rep(i,0,n - 1) a1[i] = a1[i] * b1[i] % mod;
rep(i,0,n - 1) a2[i] = a2[i] * b2[i] % mod;
ntt(a1,-1); ntt(a2,-1);
len2 --; len1--;
rep(i,len2,len1) if((a1[i] - 2 * a2[i] + sum) % mod == 0) ans++;
cout << ans << endl;
rep(i,len2,len1) if((a1[i] - 2 * a2[i] + sum) % mod == 0) printf("%d\n",i - len2);
return 0;
}