poj1200 字符串hash 滚动哈希初探
假如要判断字符串A“AABA”是否是字符串B“AABAACAADAABAABA”的子串
最朴素的算法是枚举B的所有长度为4的子串,然后逐个与A进行对比,这样的时间复杂度是O(mn),m为A的长度,n为B的长度。
另一个做法是用哈希函数计算出A的哈希值,然后计算出B所有长度为4的子串的哈希值,这样比较就可以判断出A是否在B中。虽然这样做的时间复杂度还是O(mn),但是为接下来的滚动哈希打下了基础。
Rabin-Karp算法采用了一种叫做滚动哈希的技巧,对哈希函数的类型有要求。
Rabin-Karp算法的思想:
- 假设待匹配字符串的长度为M,目标字符串的长度为N(N>M);
- 首先计算待匹配字符串的hash值,计算目标字符串前M个字符的hash值;
- 比较前面计算的两个hash值,比较次数N-M+1:
- 若hash值不相等,则继续计算目标字符串的下一个长度为M的字符子串的hash值
- 若hash值相同,则需要使用朴素算法再次判断是否为相同的字串;
哈希函数定义如下。
其中Cm表示字符串中第m项所代表的特地数字,有很多种定义方法,我习惯于用java自带的char值,也就是ASCII码值。java中的char是16位的,用的Unicode编码,8位的ASCII码包含在Unicode中。
b是哈希函数的基数,相当于把字符串看作是b进制数。
h是防止哈希值溢出。
滚动哈希的技巧就是:如果已经算出从k到k+m的子串的哈希值H(S[k,k+1...k+m]),那么从k+1到k+m+1的子串的哈希值就可以基于前一个的哈希值计算得出
在不考虑哈希碰撞的前提下,Rabin-Karp算法的时间复杂度就是O(m+n)。
那么来看看POJ 1200
题目大意是有一个字符串,其中有NC种不同的字符,求出其长度为N的不同子串的个数。
这个题目的本意是要利用这个NC,但是我这里只是为了训练滚动哈希,就没有用NC。可以把哈希函数的基数b设为NC,就相当于把字符串转换成了NC进制
- import java.util.HashSet;
- import java.util.Scanner;
- public class test {
- static long pat; //原始长度为n的子串的哈希值
- static long next; //右移一位子串的哈希值
- static long B = 100000007; //哈希函数基数
- static long max = Integer.MAX_VALUE; //取模防止哈希值溢出
- public static void main(String[] args) {
- HashSet<Long> res = new HashSet<Long>(); //把子串的哈希值放入hashset中,hashset的size就是所求子串个数
- Scanner scanner = new Scanner(System.in);
- int n = scanner.nextInt();
- int nc = scanner.nextInt();
- scanner.nextLine();
- String buff = scanner.nextLine();
- char[] s = buff.toCharArray();
- long t = 1;
- //计算出B的n次方
- for (int i = 0; i < n; i++) {
- t = (t * B) % max;
- }
- //计算出第一个子串的哈希值
- for (int i = 0; i < n; i++) {
- pat = (pat * B + s[i]) % max;
- }
- next = pat;
- res.add(next);
- //没有考虑哈希冲突,直接右移计算
- for (int i = 0; i + n < s.length; i++) {
- next = (next * B + s[i + n] - s[i] * t) % max;
- res.add(next);
- }
- System.out.println(res.size());
- }
- }
poj1200 字符串hash 滚动哈希初探的更多相关文章
- Redis支持的数据类型及相应操作命令:String(字符串),Hash(哈希),List(列表),Set(集合)及zset(sorted set:有序集合)
help 命令,3种形式: help 命令 形式 help @<group> 比如:help @generic.help @string.help @hash.help @list.hel ...
- 字符串HASH 学习总结 && 模板
一.字符串HASH模板 取自挑战程序设计竞赛(第2版) </pre><pre code_snippet_id="446698" snippet_file_nam ...
- Swift3.0语言教程获取字符串编码与哈希地址
Swift3.0语言教程获取字符串编码与哈希地址 Swift3.0语言教程获取字符串编码与哈希地址,以下将讲解字符串中其它内容的获取方法. 1.获取字符串编码 在NSString中可以使用2个属性获取 ...
- 各种字符串Hash函数比较(转)
常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法.这些函数使用位运算使得每一个字符都对最后的函数值产生影响.另外还有以MD5和SHA1为代表的杂凑函数,这些函数几乎 ...
- [转]各种字符串Hash函数比较
转自:https://www.byvoid.com/zht/blog/string-hash-compare 常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法.这些 ...
- 【转】各种字符串Hash函数比较
常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法.这些函数使用位运算使得每一个字符都对最后的函数值产生影响.另外还有以MD5和SHA1为代表的杂凑函数,这些函数几乎 ...
- POJ 3865 - Database 字符串hash
[题意] 给一个字符串组成的矩阵,规模为n*m(n<=10000,m<=10),如果某两列中存在两行完全相同,则输出NO和两行行号和两列列号,否则输出YES [题解] 因为m很小,所以对每 ...
- [T]各种字符串Hash函数比较
常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法.这些函数使用位运算使得每一个字符都对最后的函数值产生影响.另外还有以MD5和SHA1为代表的杂凑函数,这些函数几乎 ...
- 各种字符串Hash函数比较
常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法.这些函数使用位运算使得每一个字符都对最后的函数值产生影响.另外还有以MD5和SHA1为代表的杂凑函数,这些函数几乎 ...
随机推荐
- css3中有关transform的问题
Transform属性应用于元素的2D或3D转换.这个属性允许你将元素旋转,缩放,移动,倾斜等.
- Redis集群整合到springboot框架
整合步骤 1 配置application.properties spring.redis.cluster.nodes=192.168.60.131:8000,192.168.60.131:8001,1 ...
- RMAN备份与恢复(三)--备份相关概念
(1)备份对象 可以使用RMAN进行的备份对象如下: --整个数据库:备份所有的数据文件和控制文件: --数据文件:备份指定的一个或多个数据文件: --表空间:备份指定的一个或多个表空间: --归档重 ...
- DRF知识
- Percona XtraDB Cluster 5.7安装配置
优点:1.准同步复制2.多个可同时读写节点,可实现写扩展,较分片方案更进一步3.自动节点管理4.数据严格一致5.服务高可用缺点:1.只支持innodb引擎2.所有表都要有主键3.所有的写操作都将发生在 ...
- linux 查看系统当前时间,修改时间
linux 查看系统当前时间,修改时间1. 查看时间和日期命令 : "date"2.设置时间和日期例如:将系统日期设定成2018年6月8日的命令命令 : "date -s ...
- 使用CSS3制作首页登录界面实例
响应式设计 在这个页面中,使用下面3点来完成响应式设计 1.最大宽度 .设定了一个 max-width 的最大宽度,以便在大屏幕时兼容.: 2.margin : 30px auto; 使其保持时刻居中 ...
- 宝塔漏洞 XSS窃取宝塔面板管理员漏洞 高危
宝塔是近几年刚崛起的一款服务器面板,深受各大站长的喜欢,windows2003 windows2008windosws 2012系统,linux centos deepin debian fedora ...
- A*与IDA*的奇妙之旅
因为A*卡了一天QAQ 那么,A*是什么呢? A* A*是对于bfs的优化,启发式搜索. 例如下图: 不错,在这张图上,小人去找电脑,用bfs的话: 黄色就是bfs的搜索范围...不要问我为什么选黄色 ...
- C# 实现窗口无边框,可拖动效果
#region 无边框拖动效果 [DllImport("user32.dll")]//拖动无窗体的控件 public static extern bool ReleaseCaptu ...