CF528D Fuzzy Search 和 BZOJ4259 残缺的字符串
Fuzzy Search
给你文本串 S 和模式串 T,求 S 的每个位置是否能模糊匹配上 T。
这里的模糊匹配指的是把 T 放到 S 相应位置上之后,T 中每个字符所在位置附近 k 个之内的位置上的 S 的字符至少有一个与之相同。
1 ≤ |T| ≤ |S| ≤ 200 000, 0 ≤ k ≤ 200 000。字符串是基因序列。
题解
由于字符集很小,所以对每种字符分别处理。
对 T 每个位置赋值为它是否等于这个字符。对 S 的每个位置前后找找有没有这种字符即可。
然后卷积看看匹配了多少个位置。每种字符的匹配位置数加起来等于 T 的长度的话,匹配就成功了。
时间复杂度 \(O(n \log n)\)。
struct node {LD x,y;};
IN node operator+(CO node&a,CO node&b){
return (node){a.x+b.x,a.y+b.y};
}
IN node operator-(CO node&a,CO node&b){
return (node){a.x-b.x,a.y-b.y};
}
IN node operator*(CO node&a,CO node&b){
return (node){a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x};
}
IN node operator/(CO node&a,LD k){
return (node){a.x/k,a.y/k};
}
CO int N=524288;
char s[N],t[N];
int cnt[100];
node sa[N],sg[N],sc[N],st[N];
node ta[N],tg[N],tc[N],tt[N];
node res[N];
bool ans[N];
CO LD pi=acos(-1),eps=1e-6;
int rev[N];
node omg[N];
void FFT(node a[],int lim){
for(int i=0;i<lim;++i)
if(i<rev[i]) swap(a[i],a[rev[i]]);
for(int i=1;i<lim;i<<=1)
for(int j=0;j<lim;j+=i<<1)
for(int k=0;k<i;++k){
node t=omg[lim/(i<<1)*k]*a[j+i+k];
a[j+i+k]=a[j+k]-t,a[j+k]=a[j+k]+t;
}
}
int main(){
int n=read<int>(),m=read<int>(),k=read<int>();
scanf("%s%s",s,t);
reverse(t,t+m);
for(int i=0;i<m;++i){
if(t[i]=='A') ta[i]=(node){1,0};
else if(t[i]=='G') tg[i]=(node){1,0};
else if(t[i]=='C') tc[i]=(node){1,0};
else tt[i]=(node){1,0};
}
for(int i=0;i<n;++i){
++cnt[s[i]];
if(cnt['A']) sa[i]=(node){1,0};
if(cnt['G']) sg[i]=(node){1,0};
if(cnt['C']) sc[i]=(node){1,0};
if(cnt['T']) st[i]=(node){1,0};
if(i>=k) --cnt[s[i-k]];
}
memset(cnt,0,sizeof cnt);
for(int i=n-1;i>=0;--i){
++cnt[s[i]];
if(cnt['A']) sa[i]=(node){1,0};
if(cnt['G']) sg[i]=(node){1,0};
if(cnt['C']) sc[i]=(node){1,0};
if(cnt['T']) st[i]=(node){1,0};
if(i+k<=n-1) --cnt[s[i+k]];
}
memset(cnt,0,sizeof cnt);
for(int i=0;i<m;++i) ++cnt[t[i]];
fill(ans+m-1,ans+n,1);
int len=ceil(log2(n)),lim=1<<len;
for(int i=0;i<lim;++i) rev[i]=rev[i>>1]>>1|(i&1)<<(len-1);
for(int i=0;i<lim;++i) omg[i]=(node){cos(i*2*pi/lim),sin(i*2*pi/lim)};
FFT(sa,lim),FFT(ta,lim);
for(int i=0;i<lim;++i) res[i]=sa[i]*ta[i];
for(int i=0;i<lim;++i) omg[i].y=-omg[i].y;
FFT(res,lim);
for(int i=0;i<lim;++i) res[i]=res[i]/lim;
for(int i=0;i<lim;++i) omg[i].y=-omg[i].y;
for(int i=m-1;i<n;++i)
if(fabs(res[i].x-cnt['A'])>eps) ans[i]=0;
FFT(sg,lim),FFT(tg,lim);
for(int i=0;i<lim;++i) res[i]=sg[i]*tg[i];
for(int i=0;i<lim;++i) omg[i].y=-omg[i].y;
FFT(res,lim);
for(int i=0;i<lim;++i) res[i]=res[i]/lim;
for(int i=0;i<lim;++i) omg[i].y=-omg[i].y;
for(int i=m-1;i<n;++i)
if(fabs(res[i].x-cnt['G'])>eps) ans[i]=0;
FFT(sc,lim),FFT(tc,lim);
for(int i=0;i<lim;++i) res[i]=sc[i]*tc[i];
for(int i=0;i<lim;++i) omg[i].y=-omg[i].y;
FFT(res,lim);
for(int i=0;i<lim;++i) res[i]=res[i]/lim;
for(int i=0;i<lim;++i) omg[i].y=-omg[i].y;
for(int i=m-1;i<n;++i)
if(fabs(res[i].x-cnt['C'])>eps) ans[i]=0;
FFT(st,lim),FFT(tt,lim);
for(int i=0;i<lim;++i) res[i]=st[i]*tt[i];
for(int i=0;i<lim;++i) omg[i].y=-omg[i].y;
FFT(res,lim);
for(int i=0;i<lim;++i) res[i]=res[i]/lim;
for(int i=0;i<lim;++i) omg[i].y=-omg[i].y;
for(int i=m-1;i<n;++i)
if(fabs(res[i].x-cnt['T'])>eps) ans[i]=0;
int sum=0;
for(int i=m-1;i<n;++i) sum+=ans[i];
printf("%d\n",sum);
return 0;
}
残缺的字符串
很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n。可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同程度的残缺。
你想对这两个串重新进行匹配,其中A为模板串,那么现在问题来了,请回答,对于B的每一个位置i,从这个位置开始连续m个字符形成的子串是否可能与A串完全匹配?
1<=m<=n<=300000
两个串均仅由小写字母和*号组成,其中*号表示相应位置已经残缺。
题解
这题跟上面那道几乎一样,只不过模糊匹配的方式更改了而已。
令通配符的位置的值为0,构造
\]
ansi=0时匹配成功。
这破题还是权限题。
CF528D Fuzzy Search 和 BZOJ4259 残缺的字符串的更多相关文章
- CF528D. Fuzzy Search [FFT]
CF528D. Fuzzy Search 题意:DNA序列,在母串s中匹配模式串t,对于s中每个位置i,只要s[i-k]到s[i+k]中有c就认为匹配了c.求有多少个位置匹配了t 预处理\(f[i][ ...
- CF528D Fuzzy Search 字符串匹配+FFT
题意: DNA序列,在母串s中匹配模式串t,对于s中每个位置i,只要s[i-k]到s[i+k]中有c就认为匹配了c.求有多少个位置匹配了t. 分析: 这个字符串匹配的方式,什么kmp,各种自动机都不灵 ...
- CF-528D Fuzzy Search(FFT字符串匹配)
Fuzzy Search 题意: 给定一个模式串和目标串按下图方式匹配,错开位置不多于k 解题思路: 总共只有\(A C G T\)四个字符,那么我们可以按照各个字符进行匹配,比如按照\(A\)进行匹 ...
- BZOJ4259残缺的字符串
题目描述 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同程度的残缺. ...
- BZOJ4259 残缺的字符串(FFT)
两个串匹配时相匹配的位置位置差是相同的,那么翻转一个串就变成位置和相同,卷积的形式. 考虑如何使用卷积体现两个位置能否匹配.一个暴力的思路是每次只考虑一种字符,将其在一个串中设为1,并在另一个串中将不 ...
- BZOJ4259:残缺的字符串(FFT)
Description 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同 ...
- BZOJ4259 残缺的字符串 【fft】
题目 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同程度的残缺. 你想 ...
- BZOJ4259: 残缺的字符串 & BZOJ4503: 两个串
[传送门:BZOJ4259&BZOJ4503] 简要题意: 给出两个字符串,第一个串长度为m,第二个串长度为n,字符串中如果有*字符,则代表当前位置可以匹配任何字符 求出第一个字符串在第二个字 ...
- BZOJ4259 残缺的字符串 多项式 FFT
原文链接http://www.cnblogs.com/zhouzhendong/p/8798532.html 题目传送门 - BZOJ4259 题意 给你两个串,用其中一个来匹配另一个.问从母串的那些 ...
随机推荐
- 记录ssis的两个异常解决办法
1.Foreach文件枚举提示变量为空的解决办法:把foreach属性窗口中的DelayValidation设置为True就可以了 2.csv导入数据库提示:无法在 unicode 和非 unicod ...
- 统计numpy数组中每个值出现的个数
统计numpy数组中某一个值或某几个值出现的个数:sum(data==4) # 统计出现了几个cluster include0Cluster = sum(res == 0) include1Clust ...
- in 和 exists的区别
表展示 首先,查询中涉及到的两个表,一个user和一个order表,具体表的内容如下: user表: order表: in 确定给定的值是否与子查询或列表中的值相匹配.in在查询的时候,首先查询子查询 ...
- 【转】【linux】查看文件夹大小
du的用法 du命令用来查看目录或文件所占用磁盘空间的大小.常用选项组合为:du -sh du常用的选项: -h:以人类可读的方式显示 -a:显示目录占用的磁盘空间大小,还要显示其下目录和文件占用磁盘 ...
- IScroll中div点击事件触发两次解决办法
1.网上的同学说的,直接修改源代码,但是这种方法可能会影响到现有的程序. 搜索onBeforeScrollStart方法,将其中的preventDefault禁止掉搜索_end方法,将其中模拟clic ...
- C#采集UVC摄像头画面并支持旋转和分辨率切换
在项目中,我们会需要控制uvc摄像头,采集其实时画面,或者对其进行旋转.目前市面上大多数USB摄像头都支持UVC协议.那么如何采集呢?当然是采用SharpCamera!因为SharpCamera支持对 ...
- 类嵌套_list泛型_餐馆点菜例
form1内容: private void button1_Click(object sender, EventArgs e) { //声明并初始化一张点菜清单 yiduicai danzi = ne ...
- mvc_第一遍_业务逻辑层和模型
常用的动态网页对象: 之前我们提到了,使用request对象可以获得和用户请求相关的一系列信息.这一节,我们来看看另外两个常用对象的常规用途. response对象:用于向客户回应.最常用的用法类似于 ...
- tomcat8 url包含|等特殊字符报错400的问题
这个问题纠缠了我很久了,终于在今天早上解决了,感谢自己的不放弃和不断尝试的决心,我坚信,我可以找到解决方式!! 项目用的spring .spring mvc.hibernate框架,关于统一错误页面在 ...
- IDEA超级实用的几个快捷键
最近开始使用IDEA,突然发现的比较的实用的几个快捷键 这些快捷键用的好的话真的可以提升很多效率 还有一些比较简单的快捷键,相信大家都会 Ctrl+X:剪切 Ctrl+C:复制 Ctrl+V:粘贴 C ...