[CF528D]Fuzzy Search【FFT】

[CF528D]Fuzzy Search
给定母串(S)和模式串(T),字符集大小为(4),给定(k)(T)在某个位置(i)匹配,当且仅当(forall; jin [0, |T|-1], exists pin [i-k, i+k])使得(T_j=S_{i+p+j}),求(T)的匹配次数
(|S|, |T|le 2*{10}^5)
(|T|=m),
对于每个字符(c),令(a[i]=[S_i)能匹配(c])(b[i]=[T_i == c])
贡献(f[j]=sum_{i=0}^{m-1}a[j+i]*b[i]),当总贡献为(m)(j)位置为匹配位置
(d[i]=b[m-i-1]),即(d[m-i-1]=b[i]),
则$$f[j]=sum_{i=0}^{m-1}a[j+i]d[m-i-1]=(ad)(j+m-1)$$
计算卷积就好

char s[Maxn], t[Maxn];
int q[Maxn], head, tail, tot[Maxn];
void cal(char c){
	memset(f, 0, sizeof(f)); memset(g, 0, sizeof(g));
	head=1, tail=0;
	for(int i=0; i < n; i++){
		if(s[i] == c) q[++tail]=i;
		while(head <= tail && q[head]+k < i) head++;
		if(head <= tail) f[i].a=1;
	}head=1, tail=0;
	for(int i=n-1; i >= 0; i--) {
		if(s[i] == c) q[++tail]=i;
		while(head <= tail && q[head] > i+k) head++;
		if(head <= tail) f[i].a=1;
	}
	for(int i=0; i < m; i++) if(t[i] == c) g[m-i-1].a=1;
	FFT(f, 1); FFT(g, 1); for(int i=0; i < lim; i++) f[i]=f[i]*g[i]; FFT(f, -1);
	for(int i=0; i < n; i++) tot[i]+=floor(f[i+m-1].a/lim+0.5);
}

void solve(){
	n=read(), m=read(), k=read(); scanf("%s", s); scanf("%s", t);
	while(lim <= n+m-2) lim<<=1, l++;
	for(int i=0; i < lim; i++) r[i]=r[i>>1]>>1|((i&1)<<l-1);
	cal('A'); cal('G'); cal('C'); cal('T'); int ans=0;
	for(int i=0; i < n; i++) if(tot[i] >= m) ans++;
	printf("%d", ans);
}

(我真是个小天才,用(char)来存数组(orz)

原文地址:https://www.cnblogs.com/zerolt/p/9303013.html