您的位置:首页 > 其它

CF528D Fuzzy Search

2018-02-01 00:47 260 查看

Fuzzy Search

题目描述

传送门:http://codeforces.com/problemset/problem/528/D

题解

将AGTC分别考虑

考虑A字符,将S串中所有的A字符的前后k个位置都标记1

其它位置标记0

T串所有A字符都标记1

枚举S-T+1个位置暴力判定S串生成的01串在一定区间内是否和T串生成的01串相同

可以压位搞

也可以把T串翻转过来,然后就等价于判断相应位置卷积的值=T串中A的个数

将S串和T串生成的01串跑个FFT即可

其他字母同理

一个位置开始如果被四个字母同时满足则有解

代码

#include<bits/stdc++.h>
#define eps 1e-4
#define N 530005
#define Pi atan2(0,-1)
using namespace std;
int n,m,k,len,L,rev
,s
,sum
,cnt,res;
char a
,b
;
const char h[]={'A','G','T','C'};
struct comp{
double r,i;
comp operator+(const comp &x)
const{return (comp){r+x.r,i+x.i};}
comp operator-(const comp &x)
const{return (comp){r-x.r,i-x.i};}
comp operator*(const comp &x)
const{return (comp){r*x.r-i*x.i,r*x.i+i*x.r};}
}A
,B
,ans
,t
;

void DFT(comp *x,int n,int inv)
{
for(int i=0;i<n;i++)t[rev[i]]=x[i];
for(int i=0;i<n;i++)x[i]=t[i];
for(int i=1,d=2;i<=L;i++,d<<=1)
{
comp w0=(comp){cos(2*Pi*inv/d),sin(2*Pi*inv/d)},w,u,v;
for(int j=0,k;j<n;j+=d)
for(k=j,w=(comp){1,0};k<j+(d>>1);k++,w=w*w0)
u=x[k],v=x[k+(d>>1)]*w,x[k]=u+v,x[k+(d>>1)]=u-v;
}
if(inv==-1)for(int i=0;i<n;i++)x[i].r/=n;
}

int main()
{
scanf("%d%d%d %s %s",&n,&m,&k,a+1,b+1);
for(int x=0;x<4;x++)
{
char c=h[x];cnt=0;
memset(s,0,sizeof(s));
memset(A,0,sizeof(A));
memset(B,0,sizeof(B));
for(int i=1;i<=n;i++)if(a[i]==c)
s[max(1,i-k)]++,s[min(i+k+1,n+1)]--;
for(int i=1;i<=n;i++)
{
s[i]+=s[i-1];
if(s[i])A[i]=(comp){1,0};
}
for(int i=1,j=m;i<=m;i++,j--)
if(b[i]==c)B[j]=(comp){1,0},cnt++;
for(len=1,L=0;len<=max(m,n)*2;len<<=1,L++);
for(int i=0;i<len;i++)rev[i]=(rev[i>>1]>>1)|(i&1)<<(L-1);
DFT(A,len,1);DFT(B,len,1);
for(int i=0;i<len;i++)ans[i]=A[i]*B[i];
DFT(ans,len,-1);
for(int i=1;i<=n-m+1;i++)
if(fabs(ans[i+m].r-cnt)<eps)sum[i]++;
}
for(int i=1;i<=n-m+1;i++)
if(sum[i]==4)res++;
printf("%d\n",res);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: