[TJOI2017] DNA 解题报告 (hash+二分)
2024-08-29 07:54:03
题目链接:https://www.luogu.org/problemnew/show/P3763
题目大意:
给定原串S0,询问S0有多少个子串和给定串S相差不到3个字母
题解:
我们枚举S0的子串,问题转化为如何高效的判断两个串是否相差不到三个字母
考虑到数据范围,发现只能有log的时间余地
自然想到二分
solve每次找到第一个不同的位置并且返回,连续solve 4次,若S在这期间被处理完了,那么说明两个串相差不到3个字母
当然还有一些小细节
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
typedef unsigned long long ull;
const int N=1e5+;
int lena,lenb;
ull pin[N],haa[N],hab[N];
char a[N],b[N];
void H()
{
haa[]=hab[]=;
for (int i=;i<=lena;i++)
{
haa[i]=haa[i-]*+a[i]-'a';
}
for (int i=;i<=lenb;i++)
{
hab[i]=hab[i-]*+b[i]-'a';
}
}
int solve(int x,int y)
{
int l=,r=lenb;
while (l<r)
{
int mid=l+r>>;
if ((haa[x+mid-]-haa[x-]*pin[mid])==(hab[y+mid-]-hab[y-]*pin[mid]))
{
l=mid+;
}
else r=mid;
}
if (haa[x+l-]-haa[x-]*pin[l]!=hab[y+l-]-hab[y-]*pin[l])
{
return l;
}
else return l+;
}
int check(int x)
{
int now=,k;
for (int i=;i<=;i++)
{
k=solve(x,now);
//printf("%d %d %d\n",x,now,k);
x+=k;now+=k;
if (now>lenb) return ;
}
k=solve(x,now);
x+=k-;now+=k-;
if (now>=lenb) return ;
return ;
}
int main()
{
pin[]=;
for (int i=;i<=N;i++) pin[i]=pin[i-]*;
int T;
scanf("%d",&T);
while (T--)
{
scanf("%s",a+);
scanf("%s",b+);
lena=strlen(a+),lenb=strlen(b+);
H();
//printf("%d\n",solve(2,3));
int re=;
for (int i=;i<=lena-lenb+;i++)
{
if (check(i)) re++;
}
printf("%d\n",re);
}
return ;
}
最新文章
- Get radio selected value
- 激活windows7 企业版小记
- 坦克大战,看你能坚持几秒 ~~Duang~~Duang
- Windows10的快捷键和新功能你利用了多少?
- MySQL基础二
- 常用jQuery代码01
- Android IOS WebRTC 音视频开发总结(五二)-- 亲,咱一起采访webrtc大会的各路专家
- C#:vs2010无法打开vs2012创建的项目
- 叼叼叼,HTML5日期(Date)类型和文本(Text)类型互相转换
- Unity中List的随机排序(乱序)
- Ext.net MessageBox提示
- qt sleep
- 本地服务器能ping通,但是ssh及各种端口都访问不到---待整理
- SharePoint研究之表单登录配置
- CentOS 启动-运行级别
- Bash游戏(51Nod - 1046)
- Python进行数值计算
- WIN10 当中装BDM驱动
- 编译参数-ObjC的说明
- javaScript定义函数的三种方式&;amp;变量的作用域