其他分享
首页 > 其他分享> > [TJOI2017]DNA

[TJOI2017]DNA

作者:互联网

Description:

加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列S,有这个序列的碱基序列就会表现出喜欢吃藕的性状,但是研究人员发现对碱基序列S,任意修改其中不超过3个碱基,依然能够表现出吃藕的性状。现在研究人员想知道这个基因在DNA链S0上的位置。所以你需要统计在一个表现出吃藕性状的人的DNA序列S0上,有多少个连续子串可能是该基因,即有多少个S0的连续子串修改小于等于三个字母能够变成S。

Hint:

考虑分别算每个字母的匹配,再累加起来
故枚举四个字母,把原串的为该字母的位赋为1,其他赋为0,匹配串相反
这样就能不重不漏的统计出不匹配的数量
统计后直接输出<=3的位置

#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=4e5+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) a[i]=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()
{
    int T;
    cin>>T;
    while(T--) {
    memset(cnt,0,sizeof(cnt)); ans=0;
    scanf("%s %s",s,t); n=strlen(s),m=strlen(t);
    for(int i=0;i<4;++i) solve("ACTG"[i]);
    for(int i=m-1;i<n;++i) ans+=cnt[i]<=3;
    printf("%d\n",ans);
    }
    return 0;
}

标签:include,DNA,int,S0,TJOI2017,序列,return,cp
来源: https://www.cnblogs.com/list1/p/10504712.html