Codeforces 528D Fuzzy Search(FFT)
题目
Source
http://codeforces.com/problemset/problem/528/D
Description
Leonid works for a small and promising start-up that works on decoding the human genome. His duties include solving complex problems of finding certain patterns in long strings consisting of letters 'A', 'T', 'G' and 'C'.
Let's consider the following scenario. There is a fragment of a human DNA chain, recorded as a string S. To analyze the fragment, you need to find all occurrences of string T in a string S. However, the matter is complicated by the fact that the original chain fragment could contain minor mutations, which, however, complicate the task of finding a fragment. Leonid proposed the following approach to solve this problem.
Let's write down integer k ≥ 0 — the error threshold. We will say that string T occurs in string S on position i (1 ≤ i ≤ |S| - |T| + 1), if after putting string T along with this position, each character of string T corresponds to the some character of the same value in string S at the distance of at most k. More formally, for any j (1 ≤ j ≤ |T|) there must exist such p (1 ≤ p ≤ |S|), that |(i + j - 1) - p| ≤ k and S[p] = T[j].
For example, corresponding to the given definition, string "ACAT" occurs in string "AGCAATTCAT" in positions 2, 3 and 6.
Note that at k = 0 the given definition transforms to a simple definition of the occurrence of a string in a string.
Help Leonid by calculating in how many positions the given string T occurs in the given string S with the given error threshold.
Input
The first line contains three integers |S|, |T|, k (1 ≤ |T| ≤ |S| ≤ 200 000, 0 ≤ k ≤ 200 000) — the lengths of strings S and T and the error threshold.
The second line contains string S.
The third line contains string T.
Both strings consist only of uppercase letters 'A', 'T', 'G' and 'C'.
Output
Print a single number — the number of occurrences of T in S with the error threshold k by the given definition.
Sample Input
10 4 1
AGCAATTCAT
ACAT
Sample Output
3
分析
题目大概相当于说给一个主串和模式串,主串各个位置i的字符可以等价于[i-k,i+k]位置中的任意一个字符,问模式串在主串中能匹配几次。
首先O(n)扫一遍主串就可以预处理出主串各个位置等价的字符集合,然后就是主串有多少个子串和模式串匹配的问题了。
这其实是FFT的经典应用:快速求出模式串某字符在主串所有位置中有多少个被匹配。通过枚举各个字符反转模式串构造多项式用FFT求乘积即可得出,LA4671。
代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define INF (1<<30)
#define MAXN 555555
const double PI=acos(-1.0); struct Complex{
double real,imag;
Complex(double _real,double _imag):real(_real),imag(_imag){}
Complex(){}
Complex operator+(const Complex &cp) const{
return Complex(real+cp.real,imag+cp.imag);
}
Complex operator-(const Complex &cp) const{
return Complex(real-cp.real,imag-cp.imag);
}
Complex operator*(const Complex &cp) const{
return Complex(real*cp.real-imag*cp.imag,real*cp.imag+cp.real*imag);
}
void setValue(double _real=0,double _imag=0){
real=_real; imag=_imag;
}
}; int len;
Complex wn[MAXN],wn_anti[MAXN]; void FFT(Complex y[],int op){
for(int i=1,j=len>>1,k; i<len-1; ++i){
if(i<j) swap(y[i],y[j]);
k=len>>1;
while(j>=k){
j-=k;
k>>=1;
}
if(j<k) j+=k;
}
for(int h=2; h<=len; h<<=1){
Complex Wn=(op==1?wn[h]:wn_anti[h]);
for(int i=0; i<len; i+=h){
Complex W(1,0);
for(int j=i; j<i+(h>>1); ++j){
Complex u=y[j],t=W*y[j+(h>>1)];
y[j]=u+t;
y[j+(h>>1)]=u-t;
W=W*Wn;
}
}
}
if(op==-1){
for(int i=0; i<len; ++i) y[i].real/=len;
}
}
void Convolution(Complex A[],Complex B[],int n){
for(len=1; len<(n<<1); len<<=1);
for(int i=n; i<len; ++i){
A[i].setValue();
B[i].setValue();
} FFT(A,1); FFT(B,1);
for(int i=0; i<len; ++i){
A[i]=A[i]*B[i];
}
FFT(A,-1);
} char S[222222],T[222222];
int cnt[4];
int get_idx(char ch){
if(ch=='A') return 0;
if(ch=='T') return 1;
if(ch=='C') return 2;
if(ch=='G') return 3;
return -1;
} int sta[222222],ans[MAXN];
Complex A[MAXN],B[MAXN]; int main(){
for(int i=0; i<MAXN; ++i){
wn[i].setValue(cos(2.0*PI/i),sin(2.0*PI/i));
wn_anti[i].setValue(wn[i].real,-wn[i].imag);
}
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
scanf("%s%s",S,T);
int l=0,r=min(n,k)-1;
for(int i=l; i<=r; ++i) ++cnt[get_idx(S[i])];
for(int i=0; i<n; ++i){
if(i-l>k) --cnt[get_idx(S[l++])];
if(r+1<n) ++cnt[get_idx(S[++r])]; for(int j=0; j<4; ++j){
if(cnt[j]) sta[i]|=(1<<j);
}
}
for(int i=0; i<4; ++i){
for(int j=0; j<len; ++j){
A[j].setValue();
B[j].setValue();
}
for(int j=0; j<m; ++j){
if(get_idx(T[j])==i) B[m-j-1].setValue(1);
}
for(int j=0; j<n; ++j){
if(sta[j]>>i&1) A[j].setValue(1);
}
Convolution(A,B,n);
for(int j=0; j<len; ++j){
ans[j]+=(int)(A[j].real+0.5);
}
}
int res=0;
for(int i=0; i<len; ++i){
if(ans[i]==m) ++res;
}
printf("%d",res);
return 0;
}
Codeforces 528D Fuzzy Search(FFT)的更多相关文章
- 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, ...
- 【CF528D】Fuzzy Search(FFT)
[CF528D]Fuzzy Search(FFT) 题面 给定两个只含有\(A,T,G,C\)的\(DNA\)序列 定义一个字符\(c\)可以被匹配为:它对齐的字符,在距离\(K\)以内,存在一个字符 ...
- CodeForces 528D Fuzzy Search 多项式 FFT
原文链接http://www.cnblogs.com/zhouzhendong/p/8782849.html 题目传送门 - CodeForces 528D 题意 给你两个串$A,B(|A|\geq| ...
- B - Fuzzy Search (FFT)
题目链接:https://cn.vjudge.net/contest/281959#problem/B 题目大意:给你n,m,k.然后输入两个字符串,n代表第一个字符串s1,m代表第二个字符串s2,然 ...
- codeforces 528D Fuzzy Search
链接:http://codeforces.com/problemset/problem/528/D 正解:$FFT$. 很多字符串匹配的问题都可以用$FFT$来实现. 这道题是要求在左边和右边$k$个 ...
- 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]\)中有 ...
- CodeForces - 528D Fuzzy Search (FFT求子串匹配)
题意:求母串中可以匹配模式串的子串的个数,但是每一位i的字符可以左右偏移k个位置. 分析:类似于 UVALive -4671. 用FFT求出每个字符成功匹配的个数.因为字符可以偏移k个单位,先用尺取法 ...
- ●codeforces 528D Fuzzy Search
题链: http://codeforces.com/problemset/problem/528/D 题解: FFT 先解释一下题意: 给出两个字符串(只含'A','T','C','G'四种字符),一 ...
- Codeforces 286E - Ladies' Shop(FFT)
Codeforces 题面传送门 & 洛谷题面传送门 好久没刷过 FFT/NTT 的题了,写篇题解罢( 首先考虑什么样的集合 \(T\) 符合条件.我们考察一个 \(x\in S\),根据题意 ...
随机推荐
- September 10th 2016 Week 37th Saturday
An innovation that goes beyond imagination again raised the standard. 颠覆想象的创新,再一次刷新标准. An advertisem ...
- Mac系统下使用VirtualBox虚拟机安装win7--第二步 创建win7系统
第二步 创建win7系统 启动 Virtual Box 以后,点击窗口左上角的“新建”按钮,如图所示
- JQ AJAX
用AJAX方法不刷新网页使用下拉列表连接数据库 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ...
- MySQL zabbix
http://liqingbiao.blog.51cto.com/3044896/1712080
- WPA: 4-Way Handshake failed - pre-shared key may be incorrect
生成psk网址: https://www.wireshark.org/tools/wpa-psk.html 相关 bug: 重点 关注 : https://en.community.sonos.com ...
- Message Flood
Message Flood Time Limit: 1500MS Memory limit: 65536K 题目描述 Well, how do you feel about mobile phone? ...
- 浅谈config文件的使用
一.缘起 最近做项目开始使用C#,因为以前一直使用的是C++,因此面向对象思想方面的知识还是比较全面的,反而是因没有经过完整.系统的.Net方面知识的系统学习,经常被一些在C#老鸟眼里几乎是常识的小知 ...
- Howto: Connect MySQL server using C program API under Linux or UNIX
From my mailbag: How do I write a C program to connect MySQL database server? MySQL database does su ...
- phpcms v9中调用栏目及调用多个子栏目中的文章列表
调用一个指定栏目列表: {pc:content action="lists" catid="6" order="id DESC& ...
- vim用法小节
1.把一个文件的内容全选复制到另一个文件 方案一: gg"*yG 然后另外一个vim "*p "*是系统剪贴板寄存器 方案二: 打开另一个文件,然后输入 :r filen ...