●codeforces 528D Fuzzy Search
题链:
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的更多相关文章
- codeforces 528D Fuzzy Search
链接:http://codeforces.com/problemset/problem/528/D 正解:$FFT$. 很多字符串匹配的问题都可以用$FFT$来实现. 这道题是要求在左边和右边$k$个 ...
- CodeForces 528D Fuzzy Search 多项式 FFT
原文链接http://www.cnblogs.com/zhouzhendong/p/8782849.html 题目传送门 - CodeForces 528D 题意 给你两个串$A,B(|A|\geq| ...
- Codeforces 528D Fuzzy Search(FFT)
题目 Source http://codeforces.com/problemset/problem/528/D Description Leonid works for a small and pr ...
- 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]\)中有 ...
- 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, ...
- CodeForces - 528D Fuzzy Search (FFT求子串匹配)
题意:求母串中可以匹配模式串的子串的个数,但是每一位i的字符可以左右偏移k个位置. 分析:类似于 UVALive -4671. 用FFT求出每个字符成功匹配的个数.因为字符可以偏移k个单位,先用尺取法 ...
- CF 528D. Fuzzy Search NTT
CF 528D. Fuzzy Search NTT 题目大意 给出文本串S和模式串T和k,S,T为DNA序列(只含ATGC).对于S中的每个位置\(i\),只要中[i-k,i+k]有一个位置匹配了字符 ...
- 【codeforces 528D】 Fuzzy Search
http://codeforces.com/problemset/problem/528/D (题目链接) 题意 给定母串和模式串,字符集大小为${4}$,给定${k}$,模式串在某个位置匹配当且仅当 ...
- CF528D. Fuzzy Search [FFT]
CF528D. Fuzzy Search 题意:DNA序列,在母串s中匹配模式串t,对于s中每个位置i,只要s[i-k]到s[i+k]中有c就认为匹配了c.求有多少个位置匹配了t 预处理\(f[i][ ...
随机推荐
- 网络1711班 C语言第四次作业批改总结
网络1711班 C语言第四次作业批改总结 助教有话说(写在前面) 近来,有同学跟老师和助教们反映:博客作业太多太麻烦,而且对编程能力提高似乎没什么帮助?在这里我要谈一谈我的感想. 博客作业的意义? 首 ...
- 20162318 实验四 Android程序设计
北京电子科技学院(BESTI) 实 验 报 告 课程:程序设计与数据结构 班级:1623班 姓名:张泰毓 指导老师:娄老师.王老师 实验日期:2017年5月26日 实验密级:非密级 实验器材:带Lin ...
- socketpair创建双向通信的管道(全双工通信)
Linux下socketpair介绍: socketpair创建了一对无名的套接字描述符(只能在AF_UNIX域中使用),描述符存储于一个二元数组,例如sv[2] .这对套接字可以进行双工通信,每一个 ...
- android 自定义ScrollView实现背景图片伸缩(阻尼效果)
android 自定义ScrollView实现强调内容背景图片伸缩(仿多米,qq空间背景的刷新) 看到一篇文章,自己更改了一下bug: 原文地址:http://www.aiuxian.com/arti ...
- Mysql数据库的触发程序
/** **创建表 */ CREATE TABLE test1(a1 INT); CREATE TABLE test2(a2 INT); CREATE TABLE test3(a3 INT NOT N ...
- Mysql 相关操作
1.用户管理 创建用户 create user '用户名'@'IP地址' identified by '密码'; 删除用户 drop user '用户名'@'IP地址'; 修改用户 rename us ...
- JS 转换数据类型
JavaScript 是一种动态数据类型语言,变量是没有类型的,可以随机赋予任意值,若变量要转换数据类型,有两种办法:隐式转换和显式转换. 隐式转换可转换为字符串(将一个值加上字符串) 数字(在值的前 ...
- jquery 表双击某行时,取出某行中各列的数值.
<script> $(function () { $("tr").dblclick(function () { var txt = $("table tr ...
- 关于APIcloud对应C#的 wcf框架作为后台,实现多库功能
首先,我是使用ajax原来的请求方式,并没有使用apicloud中封装的请求方式. 前端代码: function makeRequest() { //alert("inside makeRe ...
- Python内置函数(59)——open
英文文档: open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, ope ...