传送门

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. python之语音识别(speech模块)

    1.原理 语音操控分为 语音识别和语音朗读两部分. 这两部分本来是需要自然语言处理技能相关知识以及一系列极其复杂的算法才能搞定,可是这篇文章将会跳过此处,如果你只是对算法和自然语言学感兴趣的话,就只有 ...

  2. Disruptor并发框架简介

    Martin Fowler在自己网站上写一篇LMAX架构的文章,在文章中他介绍了LMAX是一种新型零售金额交易平台,它能够以很低的延迟产生大量交易.这个系统是建立在JVM平台上,其核心是一个业务逻辑处 ...

  3. chrome谷歌浏览器常用快捷键搜集整理

    搜集了下面比较实用的快捷键,部分不好操作的组合键就不写了:Ctrl+N:打开新窗口. Ctrl+T:打开新标签页.Ctrl+W:关闭当前标签Alt+F4:关闭chrome浏览器Ctrl+Tab:切换到 ...

  4. iOS版本设置

    Base SDK指的是当前编译所用的SDK 版本: iOS Deployment Target指的是,编译后的 app 可在 终端的哪个 版本上运行. 设置方法: 点击xcode工程左侧项目名称-&g ...

  5. 【Linux 进程】孤儿进程、僵尸进程和守护进程

    1.孤儿进程: 孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程.孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作.孤儿进程是 ...

  6. python 标准输入输出sys.stdout. sys.stdin

    import sys, time ## print('please enter your name:')# user_input=sys.stdin.readline()# print(user_in ...

  7. 10.22JS日记

    1.js数据类型分析 (1)基础类型:string.number.boolean.null.undefined (2)引用类型:object-->json.array... 2.点运算  xxx ...

  8. Oracle_SQL(3) DML增删改

    sql语言按功能分为:数据定义语言DDL.数据操纵语言DML.数据查询语言DQL.数据控制语言DCL 一.数据操纵语言DML1.insert 新增 语法:insert into <表名> ...

  9. Java图形界面——Border

    Swing编程边框(Border)的用法总结 Java进行客户端编程,使用了大量的Swing控件,由于系统默认的边框无法满足项目的要求,不得不自己更改控件的边框样式,网上找了不少资料,本文对Swing ...

  10. html标签二

    1.没有前后顺序的信息列表<ul> <li></li> <li></li></ul>2.有序列表 <ol>  < ...