传送门

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. 今天清理C盘空间,发现Unity的一个问题

    C:\Users\Acer\AppData\LocalLow\Unity\Caches\GiCache AppData目录下,Unity占用了大量C盘空间,大概有5,6个G

  2. 20 【python】入门指南:常用数据结构

    Python内置了三种高级数据结构:list,tuple,dict list:数组,相同类型的元素组成的数组 tuple:元组,相同类型的元素组成的数组,但是这里有限定条件(长度是固定的,并且值也是固 ...

  3. Gym - 101243F Vitamins(思维+并查集)

    题意 有三种药丸,白色W>红色R>蓝色B,给你m个约束条件,问你n个药丸的颜色,不能确定颜色输出‘?’ 题解 如果1<2<3,只要找到2就能确定1和3的颜色 如果2=4,只要确 ...

  4. python使用elasticsearch模块操作elasticsearch

    1.创建索引 命令如下 from elasticsearch import Elasticsearch es = Elasticsearch([{"host":"10.8 ...

  5. 高盛昂赛 算法题先写corner case

    [方法] 字写大点,先注释框架 链表:指针走就行了,最多是两个同时一起走. 两个链表求交点 //corner case if (headA == null || headB == null) { re ...

  6. swift - VFL - 1.循环创建控件 2.metrics使用

    1. /// 创建单个热门项目itemView private func creatProcduceItemView(producrName: String , producePrice: Strin ...

  7. 在微信小程序中调用本地接口

    1.点击详情,并勾选项目设置中最后一行. 2.用小程序请求本地的后台服务接口 wx.request({ url: 'http://localhost:8090/DemoProject/myTest.d ...

  8. Composer 安装以及使用方法

    Composer 是 PHP 的一个依赖管理工具.它允许你申明项目所依赖的代码库,它会在你的项目中为你安装他们. Linux 下安装 curl -sS https://getcomposer.org/ ...

  9. pthreads v3下一些坑和需要注意的地方

    一.子线程无法访问父线程的全局变量,但父线程可以访问子线程的变量 <?php class Task extends Thread { public $data; public function ...

  10. spirng中的asm与jdk不兼容<已解决>

    转载自:spirng中的asm与jdk不兼容<已解决> 前言 不知道前面对eclipse做了什么,使用maven来创建项目,然后转成web,启动的时候一直报错.我弄了好久,还是无法解决,先 ...