详解HASH(字符串哈希)
HASH意为(散列),是OI的常用算法。
我们常用哈希的原因是,hash可以快速(一般来说是O(段长))的求出一个子段的hash值,然后就可以快速的判断两个串是否相同。
今天先讲string类的hash。
可以发现,与一个string有关的HASH值不仅仅跟每个字符的个数有关,还和字符的位子有关。
通过简单的思考,我们可以构造如图的模型:

写一个比较正常的hash模板吧
const int MOD = 100000007;
int HASH(string p)
{
int E = 1;
int ret = 0;
int tl = p.size();
for (int i=0;i<tl;i++)
ret += E*p[i], E *= EE;
return ret;
}
KMP问题
题目描述
如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置。
输入输出格式
输入格式:
第一行为一个字符串,即为s1
第二行为一个字符串,即为s2
输出格式:
一行包含一个整数,表示s2在s1中出现的位置的个数
输入输出样例
ABABABC
ABA
2
说明
时空限制:1000ms,128M
数据规模:
设s1长度为N,s2长度为M
对于30%的数据:N<=15,M<=5
对于70%的数据:N<=10000,M<=100
对于100%的数据:N<=1000000,M<=1000000
思路
首先说明:此题正解为KMP,不为hash。如果想知道KMP算法,请百度一下。
但是我们学的可是“hash”呀,不能直接预处理,如果直接预处理的话,时间为O(n*m),炸掉。
我们就可以递推:
"已知长度为m的序列a[1]...a[m],现在已知"a[1]...a[m]"的hash值为K,欲求a[2]...a[m+1]的hash值。"
我首先想到的是乘法逆元,但还有其他的更简便的方法。
可以这一样想:"改变EE的赋值方式,反过来赋值,这样的话可以直接删去第一个'a[1]*EE^(m-1)',再乘一个'EE',往后再移一位,再加上一个a[m+1]."
那么,转移方程也很容易写了,为HASH[i]=(HASH[i-1]-a[i-2]*E[1]%M+M)%M*EE%M+a[i-2+m];(HASH[i]表示a[i-1]到a[i+m-2]的hash值。
另附代码:
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,k,len1,len2;
int next1[1000001];
char s1[1000001];
char s2[1000001];
long long HASH[1000001];
long long E[1000001],M=1234567898765;
long long EE = 97;
int init()
{
long long Key=0;
int ans=0;
memset(E,0,sizeof(E));
memset(HASH,0,sizeof(HASH));
E[len2]=1;
for (int i=len2-1;i>=1;i--)
E[i]=E[i+1]*EE%M;
for (int i=1;i<=len2;i++)
HASH[1]=(HASH[1]+E[i]*(s1[i-1]))%M;
for (int i=1;i<=len2;i++)
Key=(Key+E[i]*(s2[i-1]))%M;
if (HASH[1]==Key) ans++;
for (int i=2;i<=len1-len2+1;i++)
{
HASH[i]=(HASH[i-1]-s1[i-2]*E[1]%M+M)%M*EE%M+s1[i-2+len2];
if (HASH[i]==Key) ans++;
}
printf("%d\n",ans);
}
int main(){
scanf("%s",s1) ;
scanf("%s",s2) ;
len1=strlen(s1);
len2=strlen(s2);
init();
return 0;
}
详解HASH(字符串哈希)的更多相关文章
- 多表连接的三种方式详解 hash join、merge join、 nested loop
在多表联合查询的时候,如果我们查看它的执行计划,就会发现里面有多表之间的连接方式.多表之间的连接有三种方式:Nested Loops,Hash Join 和 Sort Merge Join.具体适用哪 ...
- HASH 字符串哈希 映射转化
哈希HASH的本质思想类似于映射.离散化. 哈希,通过给不同字符赋不同的值.并且钦定一个进制K和模数,从而实现一个字符串到一个模意义下的K进制数上. 它的主要目的是判重,用于$DFS$.$BFS$判重 ...
- 详解JAVA字符串类型switch的底层原理
基础 我们现在使用的Java的版本,基本上是都支持String类型的.当然除了String类型,还有int.char.byte.short.enum等等也都是支持的.然而在其底部实现中,还是基于 整型 ...
- 数据结构作业——hash(字符串哈希)
Hash Description 给定长度为 n ( n<=1000000)的字符串,字符串仅由小写字母的前 m ( m<=6) 个字符组成,请你计算出共有多少长度为 k( k<=6 ...
- 多表连接的三种方式详解 HASH JOIN MERGE JOIN NESTED LOOP
在多表联合查询的时候,如果我们查看它的执行计划,就会发现里面有多表之间的连接方式. 之前打算在sqlplus中用执行计划的,但是格式看起来有点乱,就用Toad 做了3个截图. 从3张图里我们看到了几点 ...
- 【Python】Java程序员学习Python(七)— 文本类详解(字符串、str)
如果一个女孩子喜欢看龙猫,那么请珍惜她,呵护她 任何一门语言,字符串总是最基本也是最需要掌握的一个变量,想想入门的Hello World,输出的就是字符串. 官方文档:https://docs.pyt ...
- boost::algorithm用法详解之字符串关系判断
http://blog.csdn.net/qingzai_/article/details/44417937 下面先列举几个常用的: #define i_end_with boost::iends_w ...
- Java String类详解
Java String类详解 Java字符串类(java.lang.String)是Java中使用最多的类,也是最为特殊的一个类,很多时候,我们对它既熟悉又陌生. 类结构: public final ...
- SqlHelper帮助类_上(SQLServer数据库含Connection详解)
在操作数据库时,经常会用到自己封装的SqlHelper.这里主要对SQLServer数据库的Sqlhelper,主要用于在同一个连接中完成CRUD! 一.ADO.NET中的Connection详解: ...
随机推荐
- nginx+memcached缓存图片
1.nginx的配置如下: location ^~ /images/ { set $memcached_key "$uri"; #用URI作为key去memcached中 ...
- 【Qt开发】Qt在Windows下的三种编程环境搭建
从QT官网可以得知其支持的平台.编译器和调试器的信息如图所示: http://qt-project.org/doc/qtcreator-3.0/creator-debugger-engines.htm ...
- 《剑指offer》面试题24 二叉搜索树的后序遍历序列 Java版
(判断一个元素均不相同的序列是否为一个BST的LRD) 书中方法:首先对于二叉搜索树,左子树中的所有元素小于根节点小于右子树中的所有元素,然后后序遍历序列最后一个元素是根节点,这是我们已知的条件.这道 ...
- centos6配置本地yum源
在无法访问外网时,yum安装软件会失败,这时候可以配置yum源为本地的镜像iso来解决这个问题 1. 使用Xftp上传iso镜像文件到服务器 2. 使用如下命令新建挂载点并挂载 sudo mkdir ...
- K8S工作原理
kubernetes(k8s)是docker容器用来编排和管理的工具 我们通过kubectl向k8s Master发出指令.kubernetes Master主要是提供API Server.Sched ...
- 使用 VS Code 搭建 TypeScript 开发环境
使用 VS Code 搭建 TypeScript 开发环境 TypeScript 是 JavaScript 的超集,TypeScript 只是增强了 JavaScript 而非改变了 JavaScri ...
- Java中静态变量和实例变量的区别
静态变量属于类的级别,而实例变量属于对象的级别. 主要区别有两点: 1,存放位置不同 类变量随着类的加载存在于方法区中,实例变量随着对象的对象的建立存在于堆内存中. 2,生命周期不同 类变量的生命周期 ...
- Kibana 基本操作
es中的索引对应mysql的数据库.类型对应mysql的表.文档对应mysql的记录.映射对应mysql的索引索引:index类型:type映射:mappings 1.创建索引在kibana的Dev ...
- Vue 数据持久化
方法一:使用 localStorage 存储数据 window.localStorage.setItem(key,value) 方法二:使用 vuex-persistedstate插件 vuex 存在 ...
- Gradle Settings 类的学习
# 任务 了解 Settings 类作用于 Gradle 构建的哪个阶段? 了解 Settings 类与 settings.gradle 的关系 了解和使用 inlcude 方法 hook 初始化阶段 ...