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,si−k+1,...,si+k−1,si+ks_{i-k},s_{i-k+1},...,s_{i+k-1},s_{i+k}si−k,si−k+1,...,si+k−1,si+k中存在至少一个字符使得sj=tls_j=t_lsj=tl时,我们称sis_isi与tlt_ltl匹配。
题目会给出n,m,k,s,tn,m,k,s,tn,m,k,s,t
思路:
我们把这四种字符拆开分别求解。
设当前处理的是字符xxx,那么我们将s,ts,ts,t中分别可以跟字符xxx匹配的位置标记成为111,其余不能匹配的位置标记成000。
这样一来就可以用经典的套路来统计答案啦!
我们把操作之后的ttt翻转,然后把s,ts,ts,t做多项式乘法,算出来如果某一位hhh的值等于ttt中111的个数说明sh,h+∣t∣−1=ts_{h,h+|t|-1}=tsh,h+∣t∣−1=t,然后我们做四遍把 四次都匹配的位置数统计出来即可。
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
struct Cp{
double x,y;
friend inline Cp operator+(const Cp&a,const Cp&b){return (Cp){a.x+b.x,a.y+b.y};}
friend inline Cp operator-(const Cp&a,const Cp&b){return (Cp){a.x-b.x,a.y-b.y};}
friend inline Cp operator*(const Cp&a,const Cp&b){return (Cp){a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x};}
friend inline Cp operator/(const Cp&a,const double&b){return (Cp){a.x/b,a.y/b};}
friend inline Cp operator*(const Cp&a,const double&b){return (Cp){a.x*b,a.y*b};}
};
const int N=2e5+5;
vector<Cp>A,B;
int lim,tim,n,m,K,a[N],b[N],ans[N];
char s[N];
vector<int>pos;
inline void init(const int&up){
lim=1,tim=0;
while(lim<=up)lim<<=1,++tim;
pos.resize(lim),A.resize(lim),B.resize(lim);
for(ri i=0;i<lim;++i)pos[i]=(pos[i>>1]>>1)|((i&1)<<(tim-1));
}
const double pi=acos(-1.0);
inline void fft(vector<Cp>&a,const int&type){
Cp wn,w,a0,a1;
for(ri i=0;i<lim;++i)if(i<pos[i])swap(a[i],a[pos[i]]);
for(ri mid=1;mid<lim;mid<<=1){
wn=(Cp){cos(pi/mid),sin(pi/mid*type)};
for(ri j=0,len=mid<<1;j<lim;j+=len){
w=(Cp){1,0};
for(ri k=0;k<mid;++k,w=w*wn)a0=a[j+k],a1=w*a[j+k+mid],a[j+k]=a0+a1,a[j+k+mid]=a0-a1;
}
}
if(type==-1)for(ri i=0;i<lim;++i)a[i]=a[i]/lim;
}
struct poly{
vector<Cp>a;
poly(int k=0,Cp x=(Cp){0,0}){a.resize(k+1),a[k]=x;}
inline Cp&operator[](const int&k){return a[k];}
inline const Cp&operator[](const int&k)const{return a[k];}
inline int deg()const{return a.size()-1;}
inline poly extend(const int&k){poly ret=*this;return ret.a.resize(k+1),ret;}
friend inline poly operator*(const poly&a,const poly&b){
poly ret;
int n=a.deg(),m=b.deg();
init(a.deg()+b.deg());
for(ri i=0;i<=n;++i)A[i]=a[i];
for(ri i=n+1;i<lim;++i)A[i]=(Cp){0,0};
for(ri i=0;i<=m;++i)B[i]=b[i];
for(ri i=m+1;i<lim;++i)B[i]=(Cp){0,0};
fft(A,1),fft(B,1);
for(ri i=0;i<lim;++i)A[i]=A[i]*B[i];
return fft(A,-1),ret.a=A,ret;
}
};
inline int calc(char x){return x=='A'?1:(x=='T'?2:(x=='C'?3:4));}
inline void solve(int t){
poly x(n-1),y(m-1);
int cnt=0;
for(ri l=1,r=0,i=1;i<=n;++i){
while(i+K>r&&r<=n){
++r;
if(a[r]==t)++cnt;
}
if(i-K>l){
if(a[l]==t)--cnt;
++l;
}
x[i-1].y=0;
x[i-1].x=cnt>0;
}
int tot=0;
for(ri i=1;i<=m;++i)y[i-1].x=b[i]==t,y[i-1].y=0,tot+=y[i-1].x;
reverse(y.a.begin(),y.a.end());
x=x*y;
for(ri i=0;i+m-1<=n;++i)if((int)(x[i+m-1].x+0.5)==tot)++ans[i+1];
}
int main(){
freopen("lx.in","r",stdin);
scanf("%d%d%d",&n,&m,&K);
scanf("%s",s+1);
for(ri i=1;i<=n;++i)a[i]=calc(s[i]);
scanf("%s",s+1);
for(ri i=1;i<=m;++i)b[i]=calc(s[i]);
for(ri i=1;i<=4;++i)solve(i);
int cnt=0;
for(ri i=1;i<=n;++i)cnt+=ans[i]==4;
cout<<cnt;
return 0;
}
2019.01.26 codeforces 528D. Fuzzy Search(fft)的更多相关文章
- Codeforces 528D Fuzzy Search(FFT)
题目 Source http://codeforces.com/problemset/problem/528/D Description Leonid works for a small and pr ...
- 2019.01.26 codeforces 1096G. Lucky Tickets(生成函数)
传送门 题意简述:现在有一些号码由000~999中的某些数字组成(会给出),号码总长度为nnn,问有多少个号码满足前n2\frac n22n个数码的和等于后n2\frac n22n个数码的和(保证 ...
- 【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$个 ...
- 2019.01.26 codeforces 632E. Thief in a Shop(生成函数)
传送门 题意简述:给nnn个物件,物件iii有一个权值aia_iai,可以选任意多个.现在要求选出kkk个物件出来(允许重复)问最后得到的权值和的种类数. n,k,ai≤1000n,k,a_i\le ...
- ●codeforces 528D Fuzzy Search
题链: http://codeforces.com/problemset/problem/528/D 题解: FFT 先解释一下题意: 给出两个字符串(只含'A','T','C','G'四种字符),一 ...
- 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]\)中有 ...
随机推荐
- 1、str.join() 2、fromkeys() 3、深浅拷贝 4、set()
1. 补充基础数据类型的相关知识点 1. str. join() 把列表变成字符串 2. 列表不能再循环的时候删除. 因为索引会跟着改变 3. 字典也不能直接循环删除. 把要删除的内容记录在列表中. ...
- nexus(Maven仓库私服)的安装、配置、使用和仓库迁移
简介 Nexus下载:点击进入 Nexus 是Maven仓库管理器,如果你使用Maven,你可以从Maven中央仓库 下载所需要的构件(artifact),但这通常不是一个好的做法,你应该在本地架设一 ...
- 微信小程序——过滤器的模拟
>> 编写wxs文件——filter.wxs //1. 价格格式化 function getPriceFormat(value) { return parseFloat(isNaN(val ...
- Delphi:基于jcl的Bugsplat Crash收集单元
//BugSplat Crash模拟.net数据封装 unit uBugSplat; interface uses Windows, SysUtils, Classes, StrUtils, Shel ...
- C++ map中使用erase应该注意到的问题
注意:此程序在win环境下会出现上述描述的问题:在mac环境下第一种方式是正常运行的.Map.erase有3个重载函数: void erase(iterator position); size_typ ...
- C#字符串长度判断
string aaa = "你好123"; Label1.Text = aaa.Length.ToString(); //结果5 Label2.Text = System.Tex ...
- 可变数据类型&不可变数据类型
不同的变量在内存中有不同的存储空间,每个存储空间都有一个ID >>> a = 32 >>> id(a) # 查看ID 1571185856 >>> ...
- linux命令学习之:wc
wc(Word Count)命令用来计算数字.利用wc指令我们可以计算文件的Byte数.字数或是列数,若不指定文件名称,或是所给予的文件名为“-”,则wc指令会从标准输入设备读取数据. 命令格式 wc ...
- thinkphp两表联查并且分页
ThinkPHP中关联查询(即多表联合查询)可以使用 table() 方法或和join方法,具体使用如下例所示: 1.原生查询示例: $Model = new Model(); $sql = 'sel ...
- 使用 gitbook 写东西
会了markdown 不会用gitbook怎么可以呢 先安装 npm install gitbook -g npm install gitbook-cli -g cli使用代码是客户端的意思,要牢记 ...