[Test1.11]-T1匹配 Matching
Description:
给定两个含小写字母、通配符的字符串 \(S\), \(T\)。
出于简化问题的考虑,这里的通配符只有"\(?\)"一种。它可以匹配任意一个字符。
一个串 \(T\) 在 \(S\) 的 \({pos}\) 位置上出现,当且仅当:
∀1 ≤ i ≤ |T|, Spos+i 1 = Ti | Spos+i 1 =′?′ | Ti =′?′
你的任务是:求 T 在 S 中的出现次数。
数据范围:
|T| ≤ |S| ≤ 2 × 1e5
时限:3s
空间:128mb
Solution:
代码:
#include<iostream>
#include<cstdio>
#include<complex>
#include<cstring>
#define R register
#define ll long long
#define eps 1e-8
#define is0(x) ((x) < eps && -(x) < eps)
using namespace std;
namespace IO
{
template<class T>
void rea(T &x)
{
char ch=getchar();long long f(0);x = 0;
while(!isdigit(ch)){f|=ch=='-';ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
x = f?-x:x;
}
template<class T>
T max(T a, T b){return (a>b?a:b);}
template<class T>
T min(T a, T b){return (a<b?a:b);}
}
const long long N = 600005;
char s[N], t[N], pre[N];
long long pos[N], tot, lens, lent, ans[N];
complex<double>a[N], b[N], x[N], y[N];
void init(long long k)
{
long long len = 1<<k;
for(R long long i = 0; i < len; ++i)
pos[i] = (pos[i>>1]>>1)|((i&1)<<(k-1));
}
void fft(complex<double> *a, long long n, long long flag)
{
for(R long long i = 0; i < n; ++i) if(i < pos[i]) swap(a[i], a[pos[i]]);
for(R long long len = 1; len < n; len *= 2)
{
complex<double> wx = complex<double>(cos(M_PI/len), flag*sin(M_PI/len));
for(R long long i = 0; i < n; i += len*2)
{
complex<double> w(1, 0);
for(R long long j = i; j < i+len; ++j)
{
complex<double> x = a[j];
complex<double> y = w*a[j+len];
a[j] = x+y;
a[j+len] = x-y;
w *= wx;
}
}
}
if(flag == -1) for(R long long i = 0; i < n; ++i) a[i] /= n;
}
void solve(long long flag, long long n)
{
fft(x, n, 1);fft(y, n, 1);
for(R long long i = 0; i < n; ++i) x[i] *= y[i];
fft(x, n, -1);
for(R long long i = 0; i < n; ++i) ans[i] += (long long)(x[i].real()+0.5)*flag;
}
int main()
{
freopen("matching.in","r",stdin);
freopen("matching.out","w",stdout);
scanf("%s%s", s, pre);
lens = strlen(s), lent = strlen(pre);
for(R long long i = 0; i < lent; ++i) t[i] = pre[lent-i-1];
for(R long long i = 0; i < lens; ++i) a[i] = (double)((s[i]=='?'?0 : s[i]-'a'+1));
for(R long long i = 0; i < lent; ++i) b[i] = (double)((t[i]=='?'?0 : t[i]-'a'+1));
long long P = 1, k = 0;
while(P <= lens+lent) P <<= 1, k++;
init(k);
for(R long long i = 0; i < P; ++i) x[i] = a[i]*a[i]*a[i], y[i] = b[i];
solve(1, P);
for(R long long i = 0; i < P; ++i) x[i] = a[i], y[i] = b[i]*b[i]*b[i];
solve(1, P);
for(R long long i = 0; i < P; ++i) x[i] = a[i]*a[i], y[i] = b[i]*b[i];
solve(-2, P);
for(R long long i = lent-1; i < lens; ++i) if(is0(ans[i])) tot++;
printf("%d\n", tot);
return 0;
}