[CF528D]Fuzzy Search【FFT】

[CF528D]Fuzzy Search
给定母串\(S\)和模式串\(T\),字符集大小为\(4\),给定\(k\)\(T\)在某个位置\(i\)匹配,当且仅当\(\forall\; j\in [0, |T|-1], \exists p\in [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\)

posted @ 2018-07-13 10:18  zerolt  阅读(268)  评论(1编辑  收藏  举报