• 题目链接:

    https://www.luogu.org/problemnew/show/P3763

  • 思路:

    首先我们要用到Rabin-Karp哈希,其实就是这个:

    若\(w_{str}\)=(\(a_0\) \(p^{n-1}\)+\(a_1\) \(p^{n-2}\)+...+\(a_{n-1}\) \(p^0\))

    所以

    \(w_{pre_{i-1}}\) \(=(\) \(a_0\) \(p^{i-1}\)+\(a_1\) \(p^{i-2}\)+...+\(a_{i-1}\) \(p^0\))

    \(w_{pre_{j}}\) \(=(\) \(a_0\) \(p^{j}\)+\(a_1\) \(p^{j-1}\)+...+\(a_{j}\) \(p^0\))

    所以

    \(w_{str_{i,j}}\)

    \(=(\) \(a_i\) \(p^{j-i}\)+\(a_{i+1}\) \(p^{j-i-1}\)+...+\(a_{j}\) \(p^0\))

    \(=\) \(w_{pre_{j}}\) \(-\) \(w_{pre_{i-1}}\) \(p^{j-i+1}\)

    注意了,我这里并没有取模,而是直接直接用unsigned long long 自然溢出,这样更快

    然而,一般人都是用二分确定右端点,我自己摸索出了一个骚操作(好像又在哪里听过)----用倍增

    因为在这道题中我觉得二分的上下界可能相差比较大,虽然理论上二分平均情况下更好,但在这道题中实际测出来用倍增更快(如果之后有人用二分跑得还比我快就无视我这句话)。

    思路就是这样,其他一些细节就见代码吧.

  • 代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <iostream>
#define ri int
const int maxn=100005;
typedef long long ll;
typedef unsigned long long ull;
char a[maxn],b[maxn];
ull q[maxn],aht[maxn],bht[maxn];
int cnt=0,lena,lenb;
inline void Hash(){
ll x=0;
for(ri i=0;a[i];i++){
x=x*131+a[i]-31;
aht[i]=x;
// cout<<x<<i<<endl;
}x=0;
for(ri i=0;b[i];i++){
x=x*131+b[i]-31;
bht[i]=x;
}x=0;
return ;
}
inline int solve(int x,int y){
int k=0,p=1;
x++,y++;
while(p!=0){
if((aht[x+k+p-1]-aht[x-1-1]*q[k+p+1])==(bht[y+k+p-1]-bht[y-1-1]*q[k+p+1]))k+=p,p*=2;
else p=p/2;//cout<<l<<'*'<<r<<'*'<<mid<<endl;
while(x+k+p>lena||y+k+p>lenb)p=p/2;
}
if(a[x-1]==b[y-1])k++;
return k;
}
inline bool ok(int i){
int la=0,k;
for(ri j=1;j<=3;j++){
k=solve(i,la);
i+=k+1,la+=k+1;
if(la>=lenb){return 1;}//cout<<i<<' '<<la<<endl;
}
k=solve(i,la);
i+=k;la+=k;
// cout<<i<<' '<<la<<endl;
if(la>=lenb) return 1;
return 0;
}
int main()
{
int t;
scanf("%d",&t);
q[0]=1;
for(ri i=1;i<=100001;i++)
q[i]=(ull)q[i-1]*131;
//预处理幂,这个技巧来自https://www.cnblogs.com/sineagle/p/8490655.html
while(t--){
int cnt=0;
scanf("%s",a);
scanf("%s",b);
lena=strlen(a),lenb=strlen(b);
if(lena<lenb){printf("0\n");continue;}
Hash();
for(ri i=0;i<lena-lenb+1;i++){
if(ok(i))cnt++;
}
printf("%d\n",cnt);
memset(aht,0,sizeof(aht));
memset(bht,0,sizeof(bht));
}
return 0;
}
  • 后记:

    luogu上最快的一次跑了240ms,然而还是比不过BZOJ的dalao

luogu题解 P3763 【[TJOI2017]DNA】的更多相关文章

  1. [洛谷P3763] [TJOI2017]DNA

    洛谷题目链接:[TJOI2017]DNA 题目描述 加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列S,有这个序列的碱基序列就会表现出喜欢吃藕的性状,但是研究人员发现对碱基序列S,任意修改其 ...

  2. P3763 [TJOI2017]DNA

    链接:https://www.luogu.org/problemnew/show/P3763 题解: 挺水的一题后缀数组 枚举每一个开头用后缀数组判断能否在3次内匹配完

  3. 洛谷P3763 [Tjoi2017]DNA 【后缀数组】

    题目链接 洛谷P3763 题解 后缀数组裸题 在BZOJ被卡常到哭QAQ #include<algorithm> #include<iostream> #include< ...

  4. 洛谷P3763 [TJOI2017]DNA(后缀数组 RMQ)

    题意 题目链接 Sol 这题打死我也不会想到后缀数组的,应该会全程想AC自动机之类的吧 但知道这题能用后缀数组做之后应该就不是那么难了 首先把\(S\)和\(S0\)拼到一起跑,求出Height数组 ...

  5. 洛谷P3763 [TJOI2017]DNA(后缀自动机)

    传送门 好像用SAM写的很少诶…… 其实我一开始也没想到要用SAM的……主要是没有想到找的时候可以dfs…… 首先建一个SAM,然后跑一遍dfs,枚举一下下一位,如果相同直接继续,否则就花费一次次数来 ...

  6. bzoj4892 [TJOI2017]DNA

    bzoj4892 [TJOI2017]DNA 给定一个匹配串和一个模式串,求模式串有多少个连续子串能够修改不超过 \(3\) 个字符变成匹配串 \(len\leq10^5\) hash 枚举子串左端点 ...

  7. [TJOI2017]DNA --- 后缀数组

    [TJOI2017]DNA 题目描述 加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列S, 有这个序列的碱基序列就会表现出喜欢吃藕的性状,但是研究人员发现对碱基序列S,任意修改其中不超过3个 ...

  8. luogu题解P2312解方程--暴力模+秦九韶

    题目链接 https://www.luogu.org/problemnew/show/P2312 分析 这道题很毒啊,这么大的数. 但是如果多项式\(\sum_{i=0}^N a[i]*X^i=0\) ...

  9. [TJOI2017] DNA - 后缀数组,稀疏表

    [TJOI2017] DNA Description 求模式串与主串的匹配次数,容错不超过三个字符. Solution 枚举每个开始位置,进行暴力匹配,直到失配次数用光或者匹配成功.考虑到容错量很小, ...

随机推荐

  1. vue实现购物清单列表添加删除

    vue实现购物清单列表添加删除 一.总结 一句话总结: 基础的v-model操作,以及数组的添加(push)删除(splice)操作 1.checkbox可以绑定数组,也可以直接绑定值? 绑定数组就是 ...

  2. R-CNN/Fast R-CNN/Faster R-CNN

    一.R-CNN 横空出世R-CNN(Region CNN,区域卷积神经网络)可以说是利用深度学习进行目标检测的开山之作,作者Ross Girshick多次在PASCAL VOC的目标检测竞赛中折桂,2 ...

  3. LevelListDrawable

    用来管理一组Drawable的,我们可以为里面的drawable设置不同的level, 当他们绘制的时候,会根据level属性值获取对应的drawable绘制到画布上,根节点 为:<level- ...

  4. [maven][转]pom配置之:snapshot快照库和release发布库

    在使用maven过程中,我们在开发阶段经常性的会有很多公共库处于不稳定状态,随时需要修改并发布,可能一天就要发布一次,遇到bug时,甚至一天要发布N次.我们知道,maven的依赖管理是基于版本管理的, ...

  5. Qt编写安防视频监控系统11-动态换肤

    一.前言 Qt中的动态换肤技术是非常一流的,直接调用qApp->setStyleSheet(qss);就可以对整个应用程序进行换肤,如果样式表内容不多,或者对应的贴图不对,效率还是蛮好的,不过据 ...

  6. Jenkins+gitlab+maven持续集成

    https://blog.csdn.net/tq08g2z/article/details/79718425 https://www.jianshu.com/p/3507d8b2ac87 报错用下面解 ...

  7. mysql left join对于索引不生效的问题

    SELECT t.val, m.username FROM  test.tmp_table AS t LEFT JOIN cehome.uc_members AS m USE INDEX(`mobil ...

  8. [转]将西部数据 My Passport Wireless 移动存储连接到任何支持的云存储上

    原文标题:对西部数据 My Passport Wireless 移动存储进行 Linux 魔改 原文链接:https://linux.cn/article-8246-1.html 虽然 WD My P ...

  9. JS_&&||

    && 且 当第一个参数为flase 就懒惰了,后面那个无视了,当第一个参数为ture,再去贪婪:|| 或 当第一个参数为flase 就贪婪了,继续找和面个了,当第一个参数为ture,就 ...

  10. linux系统,CentOs7加新硬盘

    1,打开Vmware软件,添加一块新的硬盘,然后一直下一步. 2.通过CRT等终端软件,连接到机器 [root@Mysql ~]# lsblk    //检查一下硬盘分区信息 [root@Mysql ...