传送门

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)的更多相关文章

  1. Codeforces 528D Fuzzy Search(FFT)

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

  2. 2019.01.26 codeforces 1096G. Lucky Tickets(生成函数)

    传送门 题意简述:现在有一些号码由000~999中的某些数字组成(会给出),号码总长度为nnn,问有多少个号码满足前n2\frac n22n​个数码的和等于后n2\frac n22n​个数码的和(保证 ...

  3. 【CF528D】Fuzzy Search(FFT)

    [CF528D]Fuzzy Search(FFT) 题面 给定两个只含有\(A,T,G,C\)的\(DNA\)序列 定义一个字符\(c\)可以被匹配为:它对齐的字符,在距离\(K\)以内,存在一个字符 ...

  4. CodeForces 528D Fuzzy Search 多项式 FFT

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

  5. B - Fuzzy Search (FFT)

    题目链接:https://cn.vjudge.net/contest/281959#problem/B 题目大意:给你n,m,k.然后输入两个字符串,n代表第一个字符串s1,m代表第二个字符串s2,然 ...

  6. codeforces 528D Fuzzy Search

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

  7. 2019.01.26 codeforces 632E. Thief in a Shop(生成函数)

    传送门 题意简述:给nnn个物件,物件iii有一个权值aia_iai​,可以选任意多个.现在要求选出kkk个物件出来(允许重复)问最后得到的权值和的种类数. n,k,ai≤1000n,k,a_i\le ...

  8. ●codeforces 528D Fuzzy Search

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

  9. 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. linux下的C++项目创建

    CMake项目的完整构建 Linux下的CMake项目通常由几个文件夹组成.小伙伴们可以先在自己的电脑上新建一个文件夹,作为你代码的根目录,然后往里面建几个子文件夹,这里并不涉及具体的代码,只是可以作 ...

  2. 【git】gitignore

    gitignore git专门有个文件用来管理那些不被纳入版本库的文件,这个文件是 [.gitignore],所有不被包含的都能放进去,但这个是有前提的. 前提 前提是文件如果没被git客户端trac ...

  3. 【Linux 线程】线程同步《三》

    1.条件变量 条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起:另一个线程使"条件成立"(给出条 ...

  4. mysql系列(3)之 DML语句

    DML操作指的是对数据库中表记录的操作,主要包括表记录的插入(insert).更新(update).删除(delete)和查询(select). 1.插入

  5. load balancer does not have available server for client: provider

    Ask Question up vote6down votefavorite 4 I'm trying to use Feign client. Below is my feing client: i ...

  6. Java07-java语法基础(六)面向对象

    Java07-java语法基础(六)面向对象 一.格式化输出 System.out.printf(“%格式字符”,输出项); 1.格式字符: d --->int.byte.short ld -- ...

  7. ubuntu14.04 源码安装MySQL

    转发麻烦备注本站地址:http://www.cnblogs.com/cyq632694540/p/7053179.html 1.下载源码包 >wget http://dev.mysql.com/ ...

  8. 2018.3.15 css课外小知识

    1, 如果手动写动画, 最小的时间间隔是多久 为什么 多数显示器默认频率是60Hz  1s刷新60次  所以理论最小是1/60*1000ms=16.7ms 2. display:inline-bloc ...

  9. pyinstller的安装

    下载:http://www.pyinstaller.org/ 解压到目录 切换到python目录 执行命令: python.exe D:\Download\PyInstaller-2.1\setup. ...

  10. JwtBearerAppBuilderExtensions.UseJwtBearerAuthentication(IApplicationBuilder

    netcore从1.1升级到2.0时,出的错,因为使用的时Jwt token参考https://github.com/aspnet/Security/issues/1310#issuecomment- ...