题链:

http://codeforces.com/problemset/problem/528/D

题解:

FFT

先解释一下题意:

给出两个字符串(只含'A','T','C','G'四种字符),一个为文本串T(长度为n),一个为模式串S(长度为m)。

要用模式串去匹配文本串。

同时给出一个正整数k,表示允许的匹配误差范围为k,即:

如果对于T[i]和S[j],只要在T[i-k~i+k]范围中存在一个字符与S[j]相同,那么T[i]和S[j]就匹配。

求出T中有多少个位置i满足从该位置开始的长度为m的子串T[i~i+m-1]可以和S串匹配。


由于字符集很小,我们可以对每种字符处理。

假设现在只考虑'A'字符,

我们标记出T串中有哪些位置可以和A字符匹配,得到数组f,(1表示该位置匹配,0表示无法匹配)

同时也用0,1标记出S串中的A字符,得到数组g。

然后不难发现,如果让T串的第i位和S串的第j位匹配,那么匹配是否成功就可以用$f[i]*g[j]$表示

所以如果要让S串和T的第$l$位开始匹配,我们可以得到匹配的贡献$D_A(l)$:

$$D_A(l)=\sum_{k=0}^{m-1}f(l+k)g(k)$$

这个式子可以写成卷积的形式,即只需要把S串翻转一下,就可以得到:

$$D_A(l)=D_A'(l+m-1)=\sum_{k=0}^{m-1}f(l+k)g(m-1-k)$$

然后就可以用FFT求出所有的$D_A$。

同理可以的到$D_T,D_C,D_G$。

那么对于T的l位置开始的长度为m的子串是否于S串匹配,就只需要判断$D_A(l)+D_T(l)+D_C(l)+D_G(l)$是否等于m即可。

代码:

#include<bits/stdc++.h>
#define MAXN 524289
#define INF 0x3f3f3f3f
using namespace std;
const double Pi=acos(-1);
struct Complex{
double real,image;
Complex(double _real=0,double _image=0):real(_real),image(_image){}
Complex operator - () const{return Complex(-real,-image);}
friend Complex operator + (const Complex &A,const Complex &B){return Complex(A.real+B.real,A.image+B.image);}
friend Complex operator - (const Complex &A,const Complex &B){return A+(-B);}
friend Complex operator * (const Complex &A,const Complex &B){return Complex(A.real*B.real-A.image*B.image,A.image*B.real+A.real*B.image);}
}null(0,0);
int cnt[MAXN],T[MAXN],S[MAXN],order[MAXN];
Complex A[MAXN],B[MAXN];
int idx(char ch){
switch(ch){
case 'A':return 1; case 'T':return 2;
case 'C':return 3; case 'G':return 4;
}
return 0;
}
void getstring(int *s,int len){
static char ch;
for(int i=0;i<len;i++)
scanf(" %c",&ch),s[i]=idx(ch);
}
void mark(int *s,int len,int id,int lim,Complex *Y,int n){
static int last; last=-INF;
for(int i=0;i<n;i++) Y[i]=null;
for(int i=0;i<len;i++){
if(s[i]==id) last=i;
if(i-last<=lim) Y[i].real=1;
} last=INF;
for(int i=len-1;i>-1;i--){
if(s[i]==id) last=i;
if(last-i<=lim) Y[i].real=1;
}
}
void FFT(Complex *Y,int n,int sign){
for(int i=0;i<n;i++) if(i<order[i]) swap(Y[i],Y[order[i]]);
for(int d=2;d<=n;d<<=1){
Complex dw(cos(2*Pi/d),sin(sign*2*Pi/d)),w,tmp;
for(int i=0;w=Complex(1,0),i<n;i+=d)
for(int k=i;k<i+d/2;w=w*dw,k++)
tmp=w*Y[k+d/2],Y[k+d/2]=Y[k]-tmp,Y[k]=Y[k]+tmp;
}
}
int main(){
int n,m,k,N,len,ans=0;
scanf("%d%d%d",&n,&m,&k);
getstring(T,n);
getstring(S,m);
reverse(S,S+m);
for(N=1,len=0;N<n+m-1;N<<=1) len++;
for(int i=1;i<N;i++) order[i]=(order[i>>1]>>1)|((i&1)<<(len-1));
for(int id=1;id<=4;id++){
mark(T,n,id,k,A,N);
mark(S,m,id,0,B,N);
FFT(A,N,1); FFT(B,N,1);
for(int i=0;i<N;i++) A[i]=A[i]*B[i];
FFT(A,N,-1);
for(int l=0;l<n;l++) cnt[l]+=(int)((A[l+m-1].real+0.5)/N);
}
for(int l=0;l<=n;l++) if(cnt[l]==m) ans++;
printf("%d\n",ans);
return 0;
}

  

●codeforces 528D Fuzzy Search的更多相关文章

  1. codeforces 528D Fuzzy Search

    链接:http://codeforces.com/problemset/problem/528/D 正解:$FFT$. 很多字符串匹配的问题都可以用$FFT$来实现. 这道题是要求在左边和右边$k$个 ...

  2. CodeForces 528D Fuzzy Search 多项式 FFT

    原文链接http://www.cnblogs.com/zhouzhendong/p/8782849.html 题目传送门 - CodeForces 528D 题意 给你两个串$A,B(|A|\geq| ...

  3. Codeforces 528D Fuzzy Search(FFT)

    题目 Source http://codeforces.com/problemset/problem/528/D Description Leonid works for a small and pr ...

  4. Codeforces.528D.Fuzzy Search(FFT)

    题目链接 \(Descripiton\) 给出文本串S和模式串T和k,S,T为DNA序列(只含\(A,T,G,C\)).对于S中的每个位置\(i\),只要\(s[i-k]\sim s[i+k]\)中有 ...

  5. 2019.01.26 codeforces 528D. Fuzzy Search(fft)

    传送门 fftfftfft好题. 题意简述:给两个字符串s,ts,ts,t,问ttt在sss中出现了几次,字符串只由A,T,C,GA,T,C,GA,T,C,G构成. 两个字符匹配的定义: 当si−k, ...

  6. CodeForces - 528D Fuzzy Search (FFT求子串匹配)

    题意:求母串中可以匹配模式串的子串的个数,但是每一位i的字符可以左右偏移k个位置. 分析:类似于 UVALive -4671. 用FFT求出每个字符成功匹配的个数.因为字符可以偏移k个单位,先用尺取法 ...

  7. CF 528D. Fuzzy Search NTT

    CF 528D. Fuzzy Search NTT 题目大意 给出文本串S和模式串T和k,S,T为DNA序列(只含ATGC).对于S中的每个位置\(i\),只要中[i-k,i+k]有一个位置匹配了字符 ...

  8. 【codeforces 528D】 Fuzzy Search

    http://codeforces.com/problemset/problem/528/D (题目链接) 题意 给定母串和模式串,字符集大小为${4}$,给定${k}$,模式串在某个位置匹配当且仅当 ...

  9. CF528D. Fuzzy Search [FFT]

    CF528D. Fuzzy Search 题意:DNA序列,在母串s中匹配模式串t,对于s中每个位置i,只要s[i-k]到s[i+k]中有c就认为匹配了c.求有多少个位置匹配了t 预处理\(f[i][ ...

随机推荐

  1. 关于C语言的第0次作业

    1.你认为大学的学习生活.同学关系.师生关系应该是怎样的?请一个个展开描述. 我认为的大学学习生活是充实的,丰富多彩的,与高中快节奏.繁忙的生活有所不同.在上了大学我们都成熟了很多,懂得了包容与忍让, ...

  2. Alpha集合

    项目名称:城市安全风险管控系统 小组成员: 张梨贤.林静.周静平.黄腾飞 Alpha冲刺随笔 Alpha冲刺Day1 Alpha冲刺Day2 Alpha冲刺Day3 Alpha冲刺Day4 Alpha ...

  3. scrapy csvfeed spider

    class CsvspiderSpider(CSVFeedSpider): name = 'csvspider' allowed_domains = ['iqianyue.com'] start_ur ...

  4. IQKeyboardManager使用方法

    使用方法: 将IQKeyboardManager 和 IQSegmentedNextPrevious类文件加进项目中.在AppDelegate文件中写下以下一行代码: [IQKeyBoardManag ...

  5. RxSwift(一)

    文/iOS_Deve(简书作者) 原文链接:http://www.jianshu.com/p/429b5160611f 著作权归作者所有,转载请联系作者获得授权,并标注"简书作者" ...

  6. fabric.js和高级画板

    本文介绍fabric.js框架使用,以及使用fabricjs打造一个高级画板程序. 高级画板功能介绍 全局绘制颜色选择 护眼模式.网格模式切换 自由绘制 画箭头 画直线 画虚线 画圆/椭圆/矩形/直角 ...

  7. 一张图说明 Web Api 参数绑定默认规则

    请求如下: 控制器如下: 慎重说明:不管请求方式是 get 还是 post , 简单类型的参数,如 name 和 id ,其值都是从 url 里面去取. Web API 从 url 还是 body 获 ...

  8. Jenkins 安装、配置与项目新建及构建

    1.Jenkins的安装与配置 1.1 java环境配置 Jenkins基于Java, Linux下安装java只要配置java环境变量即可. 首先,解压java到相应目录,我一般习惯把安装的软件放到 ...

  9. 自动化服务部署(一):Linux下安装JDK

    自动化测试的主要目的是为了执行回归测试.当然,为了模拟真实的用户操作,一般都是在UAT或者生产环境进行回归测试. 为了尽量避免内网和外网解析对测试结果的影响,将自动化测试服务部署在外网的服务器是比较好 ...

  10. 用C#(.NET Core) 实现简单工厂和工厂方法模式

    本文源自深入浅出设计模式. 只不过我是使用C#/.NET Core实现的例子. 前言 当你看见new这个关键字的时候, 就应该想到它是具体的实现. 这就是一个具体的类, 为了更灵活, 我们应该使用的是 ...