[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:

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
", tot);
	return 0;
}
原文地址:https://www.cnblogs.com/heanda/p/12398591.html