[CF528D] Fuzzy Search

关于匹配串T在模式串中出现的位置不一定按顺序……只需要保证位置差不过k。

于是……FFT板题

#include <bits/stdc++.h>
#define ll long long 
using namespace std;

const int N=2e5+10;
const int inf=0x3f3f3f3f;
const double Pi=acos(-1);

int ch2int(char c) {
	if(c=='A') return 1;
	if(c=='T') return 2;
	if(c=='G') return 3;
	if(c=='C') return 4;
	return 0;
}
char str[N];
int n,m,K,ans,s[N],t[N],SUM[N];
int p,pL,rev[N<<1];

struct cplx {
	double x,y;
	cplx(){} 
	cplx(double x,double y):x(x),y(y){}
	cplx operator+(const cplx&d) {return cplx(x+d.x,y+d.y);}
	cplx operator-(const cplx&d) {return cplx(x-d.x,y-d.y);}
	cplx operator*(const cplx&d) {return cplx(x*d.x-y*d.y,x*d.y+y*d.x);}
} a[N<<1],b[N<<1];

void fft(cplx*a,int type) {
	for(int i=0; i<p; ++i) if(i<rev[i]) swap(a[i],a[rev[i]]);
	for(int m=1; m<p; m<<=1) {
		cplx wm(cos(Pi/m),type*sin(Pi/m));
		for(int i=0; i<p; i+=(m<<1)) {
			cplx w(1,0),tmp;
			for(int j=0; j<m; ++j,w=w*wm) {
				tmp=w*a[m+i+j];
				a[m+i+j]=a[i+j]-tmp;
				a[i+j]=a[i+j]+tmp;
			}
		}
	}
	if(type<0) for(int i=0; i<p; ++i) a[i].x/=p;
}

void solve(int c) {
	memset(a,0,sizeof a);
	memset(b,0,sizeof b);
	for(int i=0,p=-inf; i<n; ++i) {
		if(s[i]==c) p=i;
		if(i-p<=K) a[i].x=1;
	}
	for(int i=n-1,p=inf; ~i; --i) {
		if(s[i]==c) p=i;
		if(p-i<=K) a[i].x=1;
	}
	for(int i=0; i<m; ++i) if(t[i]==c) b[m-i-1].x=1;
	fft(a,1);  fft(b,1);
	for(int i=0; i<p; ++i) a[i]=a[i]*b[i];
	fft(a,-1);
	for(int i=0; i<n; ++i) SUM[i]+=int(a[i].x+0.5);
}

int main() {
	scanf("%d%d%d",&n,&m,&K);
	scanf("%s",str); for(int i=0; i<n; ++i) s[i]=ch2int(str[i]);
	scanf("%s",str); for(int i=0; i<n; ++i) t[i]=ch2int(str[i]);
	for(p=1,pL=0; p<(n+m-1); p<<=1,pL++);
	for(int i=0; i<p; ++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(pL-1));
	for(int i=1; i<=4; ++i) solve(i);
	for(int i=0; i<n; ++i) ans+=(SUM[i]>=m);
	printf("%d\n",ans);
	return 0;
}
posted @ 2019-06-15 10:11  nosta  阅读(213)  评论(0编辑  收藏  举报