zoukankan      html  css  js  c++  java
  • 【纪中集训2019.3.13】碱基配对

    题目:

    描述

    给出长度为(n)的字符串(A)和长度为(m)的字符串(B),仅由字符(Z,P,S,B)构成;

    定义B在A中的(p)位置匹配为:对于任意的(0 lt j lt m) , 在(A_{p+j - k}到A_{p+j+k}) 间存在等于(B_{j})的字符;

    (B)(A)中所有的匹配位置;

    范围

    $1 le n,m le 2e5 , 0 le k le n $

    题解:

    可以预处理出一个字符的有效区间([i-k,i+k])

    然后依次考虑每一个字符然后取并集

    然后对于每一个字符,(FFT) 找出不合法的位置

    #include<bits/stdc++.h>
    #define ld double 
    using namespace std;
    const int N=800010;
    const ld pi=acos(-1);
    int n,m,k,rev[N],len,L,ok[N],cnt[N];
    char S[N],T[N];
    char gc(){
    	static char*p1,*p2,s[1000000];
    	if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
    	return(p1==p2)?EOF:*p1++;
    }
    int rd(){
    	int x=0;char c=gc();
    	while(c<'0'||c>'9')c=gc();
    	while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc();
    	return x; 
    }
    int gt(char *s){
    	char c=gc(),*p=s;
    	while(!isalpha(c))c=gc();
    	while(isalpha(c))*p++=c,c=gc();
    	return p-s;
    }
    struct C{
    	ld x,y;
    	C(ld _x=0,ld _y=0):x(_x),y(_y){};
    	C operator +(const C&A)const{return C(x+A.x,y+A.y);}
    	C operator -(const C&A)const{return C(x-A.x,y-A.y);}
    	C operator *(const C&A)const{return C(x*A.x-y*A.y,x*A.y+y*A.x);}
    	C operator /(const ld&A)const{return C(x/A,y/A);}
    }A[N],B[N];
    void fft(C*a,int f){
    	for(int i=1;i<len;++i)if(i<rev[i])swap(a[i],a[rev[i]]);
    	for(int i=1;i<len;i<<=1){
    		C wn=C(cos(pi/i),f*sin(pi/i));
    		for(int j=0;j<len;j+=i<<1){
    			C w=C(1,0);
    			for(int k=0;k<i;++k,w=w*wn){
    				C x=a[j+k],y=w*a[j+k+i];
    				a[j+k]=x+y,a[j+k+i]=x-y;
    			}
    		}
    	}
    	if(!~f){for(int i=0;i<len;++i)a[i]=a[i]/len;}
    }
    void solve(char x){
    	for(int i=0;i<=n;++i)cnt[i]=0;
    	for(int i=0;i<n;++i)if(S[i]==x)cnt[max(0,i-k)]++,cnt[min(n,i+k+1)]--;
    	for(int i=0;i<n;++i)cnt[i]+=cnt[i-1];
    	for(int i=0;i<n;++i)A[i]=C(!cnt[i],0);
    	for(int i=0;i<m;++i)B[m-1-i]=C(T[i]==x,0);
    	for(int i=n;i<len;++i)A[i]=C(0,0);
    	for(int i=m;i<len;++i)B[i]=C(0,0);
    	fft(A,1);fft(B,1);
    	for(int i=0;i<len;++i)A[i]=A[i]*B[i];
    	fft(A,-1);
    	for(int i=0;i<=n-m;++i){
    		ok[i]&=!(int)(A[m-1+i].x+0.1);
    	}
    }
    int main(){
    	freopen("base.in","r",stdin);
    	freopen("base.out","w",stdout);
    	k=rd();n=gt(S);m=gt(T);
    	for(L=0,len=1;len<n+m;len<<=1,L++);
    	for(int i=1;i<len;++i){rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));}
    	if(n<m){puts("0");return 0;}
    	for(int i=0;i<=n-m;++i)ok[i]=1;
    	solve('Z');
    	solve('P');
    	solve('S');
    	solve('B');
    	int ans=0;
    	for(int i=0;i<=n-m;++i)if(ok[i])ans++;
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    ios中的几种多线程实现
    在mac下使用终端管理svn
    关于UIScrollViewDelegate协议中每个回调函数的意义及执行顺序的理解
    UIView 及其子类对象 抖动效果的实现
    ios、andriod、cocos2d 视图层次理解
    委托  通知中心   监听/观察
    iphone 中使用苹果禁用的私有Framework
    关于苹果官方网站Reachability检测网络的总结
    iOS设备的分辨率
    ios开发多线程、网络请求的理解 错误码的理解
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10532904.html
Copyright © 2011-2022 走看看