zoukankan      html  css  js  c++  java
  • [CF528D]Fuzzy Seach

    Description:

    有两个基因串S和T,他们只包含AGCT四种字符。现在你要找出T在S中出现了几次。 有一个门限值k≥0。T在S的第i(1≤i≤|S|-|T|+1)个位置中出现的条件如下:把T的开头和S的第i个字符对齐,然后T中的每一个字符能够在S中找到一样的,且位置偏差不超过k的,那么就认为T在S的第i个位置中出现。也就是说对于所有的 j (1≤j≤|T|),存在一个 p (1≤p≤|S|),使得|(i+j-1)-p|≤k 和[p]=T[j]都成立。 例如,根据这样的定义"ACAT"出现在"AGCAATTCAT"的第2,3和6的位置。
    如果k=0,那么这个就是经典的字符串匹配问题。 现在给定门限和两个基因串S,T,求出T在S中出现的次数

    Hint:

    (n le 2*10^5)

    Solution:

    其实k就相当于左右k格都能匹配到这个字符
    故由于只有4种字符,我们可以单个考虑
    每次O(n)把该字符的位置处理好
    再累加看看是否cnt==m即可

    #include <map>
    #include <set>
    #include <stack>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define ls p<<1 
    #define rs p<<1|1
    using namespace std;
    typedef long long ll;
    const int mxn=1e6+5,inf=1e9;
    const double PI=acos(-1);
    int n,m,k,lim=1,ans,l,r[mxn],cnt[mxn];
    char s[mxn],t[mxn];
    
    inline int read() {
    	char c=getchar(); int x=0,f=1;
    	while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
    	while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
    	return x*f;
    }
    inline int chkmax(int &x,int y) {if(x<y) x=y;}
    inline int chkmin(int &x,int y) {if(x>y) x=y;}
    
    struct cp {
    	double x,y;
    	cp (double xx=0,double yy=0) {x=xx,y=yy;}
    	friend cp operator + (cp a,cp b) {
    		return cp(a.x+b.x,a.y+b.y);
    	}
    	friend cp operator - (cp a,cp b) {
    		return cp(a.x-b.x,a.y-b.y);
    	}
    	friend cp operator * (cp a,cp b) {
    		return cp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
    	}
    }a[mxn],b[mxn];
    
    void FFT(cp *p,int opt) 
    {
    	for(int i=0;i<lim;++i)
    		if(i<r[i]) swap(p[i],p[r[i]]);
    	for(int mid=1;mid<lim;mid<<=1) {
    		cp wn=cp(cos(PI/mid),opt*sin(PI/mid));
    		for(int len=mid<<1,j=0;j<lim;j+=len) {
    			cp w(1,0);
    			for(int k=0;k<mid;++k,w=w*wn) {
    				cp x=p[j+k],y=w*p[j+mid+k];
    				p[j+k]=x+y,p[j+mid+k]=x-y;
    			}
    		}
    	}	
    }
    
    void solve(char c) {
    	memset(a,0,sizeof(a)); memset(b,0,sizeof(b));
    	for(int i=0,las=-inf;i<n;++i) {
    		if(s[i]==c) las=i;
    		if(i-las<=k) a[i].x=1;
    	}
    	for(int i=n-1,las=inf;i>=0;--i) {
    		if(s[i]==c) las=i;
    		if(las-i<=k) a[i].x=1;
    	}
    	for(int i=0;i<m;++i) b[i].x=t[m-i-1]==c;
    	lim=1,l=0;
    	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));
    	FFT(a,1); FFT(b,1); 
    	for(int i=0;i<=lim;++i) a[i]=a[i]*b[i];
    	FFT(a,-1);
    	for(int i=0;i<lim;++i) cnt[i]+=(int )(a[i].x/lim+0.5);
    }
    
    int main()
    {
    	n=read(); m=read(); k=read();
    	scanf("%s %s",s,t);
    	for(int i=0;i<4;++i) solve("ACTG"[i]);
    	for(int i=0;i<n+m;++i) ans+=cnt[i]==m;
    	printf("%d",ans);
        return 0;
    }
    
    
  • 相关阅读:
    CodeForces 219D Choosing Capital for Treeland (树形DP)
    POJ 3162 Walking Race (树的直径,单调队列)
    POJ 2152 Fire (树形DP,经典)
    POJ 1741 Tree (树的分治,树的重心)
    POJ 1655 Balancing Act (树的重心,常规)
    HDU 2196 Computer (树形DP)
    HDU 1520 Anniversary party (树形DP,入门)
    寒门子弟
    JQuery选择器(转)
    (四)Web应用开发---系统架构图
  • 原文地址:https://www.cnblogs.com/list1/p/10504734.html
Copyright © 2011-2022 走看看