【Codeforces】528D. Fuzzy Search-FFT&模式串匹配

版权声明:欢迎转载(请附带原链接)ヾ(๑╹◡╹)ノ" https://blog.csdn.net/corsica6/article/details/84871565

传送门:cf528D


题解

按照模式串匹配套路,不妨设 S i , 1 , S i , 2 , S i , 3 , S i , 4 = 1 / 0 S_{i,1},S_{i,2},S_{i,3},S_{i,4}=1/0 分别表示与位置 i i 距离不超过 k k 的位置上有/没有 A , T , G , C A,T,G,C ,并将 T T 翻转。

但发现式子中还是有 i = 1 4 \prod\limits_{i=1}^4 不好卷积,且 i i 位置的值实际上只与 T i T_i 对应的字母有关。而字符集大小又很小。。。

所以考虑依次枚举当前匹配的字符,如果所有情况都满足条件那么就匹配上了。


代码

#include<bits/stdc++.h>
#define ld long double
using namespace std;
const int M=2e5+10,N=2e6+100;
const ld pi=acos(-1.0);

int n,m,K,c[M],ans,ss[M];
int rv[N],len,L;
char s[M],t[M];

struct cc{
   ld r,i;
   cc(ld r_=0,ld i_=0):r(r_),i(i_){};
   cc operator +(const cc &A){return cc(r+A.r,i+A.i);}
   cc operator -(const cc &A){return cc(r-A.r,i-A.i);}
   cc operator *(const cc &A){return cc(r*A.r-i*A.i,i*A.r+A.i*r);}
   cc operator /(const ld &A){return cc(r/A,i/A);}
   inline cc conj(){return cc(r,-i);}
}f[N],g[N],rp;

inline void fft(cc *e,int pr)
{
	int i,j,k;cc ix,iy,ori,pd;
	for(i=1;i<len;++i) if(i<rv[i]) swap(e[i],e[rv[i]]);
	for(i=1;i<len;i<<=1){
		ori=cc(cos(pi/i),pr*sin(pi/i));
		for(j=0;j<len;j+=(i<<1)){
			pd=cc(1,0);
			for(k=0;k<i;++k,pd=pd*ori){
				ix=e[j+k];iy=pd*e[i+j+k];
				e[j+k]=ix+iy;e[i+j+k]=ix-iy;
			}
		}
	}
	if(pr==1) return;
	for(i=0;i<len;++i) e[i]=e[i]/(ld)len;
}

inline void ck(int alp)
{
	int i,j;memset(c,0,sizeof(c));
	for(i=0;i<m;++i) f[i].i=(t[i]==alp)?1.0:0;
	for(i=m;i<len;++i) f[i].i=0;
	for(i=0;i<n;++i) if(s[i]==alp) c[max(0,i-K)]++,c[min(n,i+K+1)]--;
	for(i=0;i<n;++i){f[i].r=(c[i]>0)?0.0:1.0;c[i+1]+=c[i];}
	for(i=n;i<len;++i) f[i].r=0;
	fft(f,1);rp=cc(0,0.25);
	for(i=0;i<len;++i){
		j=(len-i)&(len-1);
		g[i]=((f[j]*f[j]).conj()-f[i]*f[i])*rp;
	}
	fft(g,-1);
	for(i=m-1;i<n;++i) ss[i]+=(int)(g[i].r+0.5);
}

int main(){
	int i;scanf("%d%d%d%s%s",&n,&m,&K,s,t);
	reverse(t,t+m);
	for(len=1;len<n+m;len<<=1) L++;
	for(i=1;i<len;++i) rv[i]=((rv[i>>1]>>1)|((i&1)<<(L-1)));
	ck('A');ck('T');ck('G');ck('C');
	for(i=m-1;i<n;++i) if(ss[i]==0) ans++;
	printf("%d",ans); 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/corsica6/article/details/84871565