• 题目链接:

    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. sqlplus 导出一张表数据

    内网只让用sql developer 这软件搓的不行,数据加载到51行就黑了,没法法用sqlplus. 打开cmd, sqlplus user/passwd@ip:port/库名set colsep ...

  2. git 新建仓库第一次提交

    1 . git init //初始化仓库,在初始化的目录中会出现.git的文件夹 2. git add .(文件name) //添加文件到本地仓   3. git commit -m "fi ...

  3. P5657 格雷码【民间数据】

    P5657 格雷码[民间数据] 题解 其实这题水啊 打表找规律 [1]0   1 [2]00   01  11  10 [3]000   001   011   010   110   111   1 ...

  4. SPSS python教程:[1]安装Python Essentials

    python机器学习-乳腺癌细胞挖掘(博主亲自录制视频)https://study.163.com/course/introduction.htm?courseId=1005269003&ut ...

  5. Oracle 的 oracle 数据库分类

    一.数据库分类 1.小型数据库:access.foxbase 2.中型数据库:informix.sql server.mysql 3.大型数据库:sybase.db2.oracle 二.项目中如何合理 ...

  6. oracle 中SQL 语句开发语法 SELECT INTO含义

    oracle 中SQL 语句开发语法 SELECT INTO含义 在ORACLE中SELECT INTO是如何使用的,什么意思?和SQL SERVER的不一样?   和sqlserver的不一样sql ...

  7. ifc解析与渲染

  8. PAT 甲级 1013 Battle Over Cities (25 分)(图的遍历,统计强连通分量个数,bfs,一遍就ac啦)

    1013 Battle Over Cities (25 分)   It is vitally important to have all the cities connected by highway ...

  9. 将ByteBuffer保存成文件

    String dest = "d:/download/" + name; Path path = Paths.get(dest).getParent().toAbsolutePat ...

  10. lua调用的c函数模块命名规则

    比如lua中调用C函数 socket.core() , 在c中需要这样命名:luaopen_socket_core(); 基本模式是添加luaopen_前缀,讲.变为_