[Codeforces 580D]Fizzy Search(FFT)

题面

给定母串和模式串,字符集大小为4,给定k,模式串在某个位置匹配当且仅当任意位置模式串的这个字符所对应的母串的位置的左右k个字符之内有一个与它相同的,求模式串能全部匹配的次数。

分析

我们先考虑\(k=0\)的情况,即一般的字符串匹配。设母串为\(S\),模式串为\(T\),\(ans_i\)表示母串从\(i\)位置开始与\(T\)匹配,能够匹配的字符个数(注意:当遇到不匹配的字符时仍继续匹配,直到匹配完整个串)

\[ans_p=\sum_{i=1}^m [S_{p+i-1}=T_i]
\]

注意到\((p+i-1)+i\)不是常数,不符合卷积的形式。令\(T_i=T_{m-i+1}\),则

\[ans_p=\sum_{i=1}^m [S_{p+i-1}=T_{m-i+1}]
\]

这样\((p+i-1)+(m-i+p)=m+p\)为常数,符合卷积的形式。但是现在仍然无法FFT处理。

容易发现,每个字符的贡献(即这个字符的匹配个数)是可加的。那么我们可以枚举字符\(c\),设\(a_{i-1}=[S_i=c],b_{m-i}=[T_i=c]\),这样\(a\)和\(b\)卷积时只有两个位置都为1的时候匹配,对答案产生1的贡献。因此\(ans_i+=(a \cdot b)_i\).枚举完字符后,只需要遍历\(ans\)序列,如果\(ans_i=m\),则说明该位置能够与\(T\)匹配

对于\(k>0\)的情况,我们只需要稍加修改\(a\)的定义。若\([i-k,i+k]\)中存在字符\(c\),则我们令\(a_{i-1}=1\),否则为0. 可以预处理前缀和来判断。这样就可以FFT了

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define maxn 1048576
#define maxc 4
using namespace std;
const double pi=acos(-1.0);
struct com{
double real;
double imag;
com(){ }
com(double _real,double _imag){
real=_real;
imag=_imag;
}
com(double x){
real=x;
imag=0;
}
void operator = (const com x){
this->real=x.real;
this->imag=x.imag;
}
void operator = (const double x){
this->real=x;
this->imag=0;
}
friend com operator + (com p,com q){
return com(p.real+q.real,p.imag+q.imag);
}
friend com operator + (com p,double q){
return com(p.real+q,p.imag);
}
void operator += (com q){
*this=*this+q;
}
void operator += (double q){
*this=*this+q;
}
friend com operator - (com p,com q){
return com(p.real-q.real,p.imag-q.imag);
}
friend com operator - (com p,double q){
return com(p.real-q,p.imag);
}
void operator -= (com q){
*this=*this-q;
}
void operator -= (double q){
*this=*this-q;
}
friend com operator * (com p,com q){
return com(p.real*q.real-p.imag*q.imag,p.real*q.imag+p.imag*q.real);
}
friend com operator * (com p,double q){
return com(p.real*q,p.imag*q);
}
void operator *= (com q){
*this=(*this)*q;
}
void operator *= (double q){
*this=(*this)*q;
}
friend com operator / (com p,double q){
return com(p.real/q,p.imag/q);
}
void operator /= (double q){
*this=(*this)/q;
}
void print(){
printf("%lf + %lf i ",real,imag);
}
};
int rev[maxn+5];
void fft(com *x,int n,int type){
for(int i=0;i<n;i++) if(i<rev[i]) swap(x[i],x[rev[i]]);
for(int len=1;len<n;len*=2){
int sz=len*2;
com wn1=com(cos(2*pi/sz),type*sin(2*pi/sz));
for(int l=0;l<n;l+=sz){
int r=l+len-1;
com wnk=1;
for(int i=l;i<=r;i++){
com tmp=x[i+len];
x[i+len]=x[i]-wnk*tmp;
x[i]=x[i]+wnk*tmp;
wnk=wnk*wn1;
}
}
}
if(type==-1) for(int i=0;i<n;i++) x[i]/=n;
} inline int get_id(char c){
if(c=='A') return 0;
else if(c=='T') return 1;
else if(c=='G') return 2;
else return 3;
}
int n,m,K;
char s[maxn+5],t[maxn+5];
int sum[maxc+5][maxn+5];
int match[maxn+5][maxc+5];//标记s的第i位周围有没有字符j com a[maxn+5],b[maxn+5];
long long ans[maxn+5];
int main(){
scanf("%d %d %d",&n,&m,&K);
scanf("%s",s+1);
scanf("%s",t+1);
for(int i=1;i<=n;i++){
for(int j=0;j<maxc;j++) sum[j][i]=sum[j][i-1]+(get_id(s[i])==j);
}
for(int i=1;i<=n;i++){
int lb=max(i-K,1);
int rb=min(i+K,n);
for(int j=0;j<maxc;j++){
if(sum[j][rb]-sum[j][lb-1]>0) match[i][j]=1;
else match[i][j]=0;
}
}
int M=n+m;
int N=1,L=0;
while(N<=M){
N*=2;
L++;
}
for(int i=0;i<N;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
for(int c=0;c<maxc;c++){
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=1;i<=n;i++){
if(match[i][c]) a[i-1]=1;
else a[i-1]=0;
}
for(int i=1;i<=m;i++){
if(get_id(t[i])==c) b[m-i]=1;
else b[m-i]=0;
}
fft(a,N,1);
fft(b,N,1);
for(int i=0;i<N;i++) a[i]*=b[i];
fft(a,N,-1);
for(int i=0;i<N;i++) ans[i]+=(long long)(a[i].real+0.5);
}
int cnt=0;
for(int i=0;i<N;i++) if(ans[i]==m) cnt++;
printf("%d\n",cnt);
}

[Codeforces 580D]Fizzy Search(FFT)的更多相关文章

  1. 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]\)中有 ...

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

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

  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

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

  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

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

  7. CF528D. Fuzzy Search [FFT]

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

  8. ●codeforces 528D Fuzzy Search

    题链: http://codeforces.com/problemset/problem/528/D 题解: FFT 先解释一下题意: 给出两个字符串(只含'A','T','C','G'四种字符),一 ...

  9. Codeforces 986D Perfect Encoding FFT 分治 高精度

    原文链接https://www.cnblogs.com/zhouzhendong/p/9161557.html 题目传送门 - Codeforces 986D 题意 给定一个数 $n(n\leq 10 ...

随机推荐

  1. 01 C语言基本介绍

    C语言特点 容易上手学习 结构化语言 执行效率高 处理的工作和活动偏底层 可以在多种计算机平台上编译(类似Java的跨平台) C语言历史 目前,C 语言是最广泛使用的系统程序设计语言之一 C 语言是最 ...

  2. 【题解】[NOI2011]阿狸的打字机

    阿狸的打字机 \(\text{Solution:}\) 首先观察三种操作:一种是插入一个字符,一种是退回上一步(回到父亲节点). 所以,我们可以对操作串进行模拟,并处理出每一个串在树上的位置. 接下来 ...

  3. css引入本地字体

    1.首先创建一个字体 @font-face { font-family: 'number_font'; //创建一个number_font字体名称 src: url('../../../style/F ...

  4. Python实现好友生日提醒

    Python实现好友生日提醒  

  5. Vue结合Django-Rest-Frameword结合实现登录认证(二)

    作者:小土豆biubiubiu 博客园:https://www.cnblogs.com/HouJiao/ 掘金:https://juejin.im/user/2436173500265335 微信公众 ...

  6. 返回头添加cookie信息

    返回类型 HttpResponseMessage //构建返回对象 var res= Request.CreateResponse(HttpStstusCode.Ok,返回体) //创建cookie对 ...

  7. 52.Qt-Charts动态显示多条折线电压值(实现示波器效果)

    Qt 5.7过后Qt添加了官方的Chart库,之前就用的比较习惯,这次把源码发出来,给入门的同学们参考参考. 效果如下所示: 1.chartsView.h如下所示: #ifndef VIEW_H #d ...

  8. java基础小程序—万年历

    package day02.xiangmu.wannianli; import java.util.Scanner; public class CalendarTest { public static ...

  9. Linux ALSA音频库(二) 环境测试+音频合成+语音切换 项目代码分享

    1. 环境测试 alsa_test.c #include <alsa/asoundlib.h> #include <stdio.h> // 官方测试代码, 运行后只要有一堆信息 ...

  10. Redis入门之认识redis(一)

    第1章 非关系型数据库 1.1 NoSQL数据库概述 1) NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL",泛指非关系型的数据库. NoSQL 不 ...