重复子串比较的核心是使用 Rabin-Karp (Rolling Hash)。

Rabin-Karp字符串编码的本质是对字符串进行哈希,将字符串之间的比较转化为编码之间的比较

有N个不同的字符,可以将字符组成的串,映射成 N进制表示的10进制数。每一个数可以代表一种字符。 去头加尾的哈希计算可以在

的时间内完成

题目A(困难)

1044. 最长重复子串
给出一个字符串 S,考虑其所有重复子串S 的连续子串,出现两次或多次,可能会有重叠)。
返回任何具有最长可能长度的重复子串。(如果 S 不含重复子串,那么答案为 ""。)示例 1:输入:"banana" 输出:"ana" 示例 2:输入:"abcd" 输出:""

二分查找 + Rabin-Karp 字符串编码

  1. 从 1 到 N 中选取子串的长度 L
  2. 检查字符串中是否存在长度为 L 的重复子串

子任务一:二分查找

如果字符串中存在长度为 L 的重复子串,那么一定存在长度为 K < L 的重复子串(选取长度为 L 的重复子串的某个长度为 K 的子串即可),因此我们可以使用二分查找的方法,找到最大的 L。

子任务二:是否存在长度为L的重复子串(Rabin-Karp 字符串编)

使用 Rabin-Karp 算法将字符串进行编码,这样只要有两个编码相同,就说明存在重复子串。

对于选取的长度 L:使用长度为 L 的滑动窗口在长度为 N 的字符串上从左向右滑动;

哈希计算公式

字符一共有26,a最小可以取26.

检查当前处于滑动窗口中的子串的编码是否已经出现过(用一个集合存储已经出现过的编码)。若已经出现过,就说明找到了长度为 L 的重复子串;若没有出现过,就把当前子串的编码加入到集合中。

注意事项:取模

最后一个需要解决的问题是,在实际的编码计算中,hash值、

可能会非常大,在 C++ 和 Java 语言中,会导致整数的上溢出。所以,需要对编码值进行取模,将编码控制在一定的范围内,防止溢出,即h = h % modulus。
h = (h * a - nums[start - 1] * aL % modulus + modulus) % modulus;
h = (h + nums[start + L - 1]) % modulus;

注意事项2:哈希冲突

取模会导致哈希冲突,既是有可能两个字符串是不同的,但是哈希值相同。后续的话学习一下hash冲突的解决方式。

最终代码

public int search(int L, int n, int[] nums) {// roll hash的base值,26个字符,用26进制玩。int a = 26;// 防止hash值溢出,使用的mod数long modulus = (long) Math.pow(10, 16);// 计算长度为L的第一个子串的 roll hash 值long h = 0;for (int i = 0; i < L; ++i)h = (h * a + nums[i]) % modulus;// 存储已出现过的hash值HashSet<Long> seen = new HashSet<>();seen.add(h);// 第一位的26的L幂 取模 : aL % moduluslong aL = 1;for (int i = 1; i <= L; ++i)aL = (aL * a) % modulus;for (int start = 1; start < n - L + 1; ++start) {// compute rolling hash in O(1) timeh = (h * a - nums[start - 1] * aL % modulus + modulus) % modulus;h = (h + nums[start + L - 1]) % modulus;if (seen.contains(h)) return start;seen.add(h);}return -1;}public String longestDupSubstring(String S) {int n = S.length();// 将字符串映射成 hash值 (26进制的数值)// 实现常数时间复杂度的滑动窗口int[] nums = new int[n];for (int i = 0; i < n; ++i)nums[i] = (int) S.charAt(i) - (int) 'a';// 二分搜索, L = 要定位的重复字符串的长度int minRepeat = 1, maxRepeat = n;int L;while (minRepeat != maxRepeat) {L = minRepeat + (maxRepeat - minRepeat) / 2;if (search(L, n, nums) != -1)minRepeat = L + 1;elsemaxRepeat = L;}int start = search(minRepeat - 1, n, nums);return start != -1 ? S.substring(start, start + minRepeat - 1) : "";}

hash 值重复_“重复”相关的问题相关推荐

  1. jdk8 stream去重复_重复文件查找和清理工具

    在Mac上怎样可以快速搜索和清理重复文件呢?小编建议您使用Tidy Up for Mac,是非常强大而使用简单的一款重复文件清理工具,Tidy Up 5带有简单的搜索模式,并且包括80多种预定义的智能 ...

  2. 同一个字符串hash值相同吗_图说:为什么Java中的字符串被定义为不可变的

    原文地址:https://dwz.cn/zWeX9Z7k 作者:Hollis 文章来源:微信公众号 字符串,想必大家最熟悉不过了,通常我们在代码中有几种方式可以创建字符串,比如:String s = ...

  3. python concat去除重复值语句_Python DataFrame使用drop_duplicates()函数去重(保留重复值,取重复值)...

    摘要 在进行数据分析时,我们经常需要对DataFrame去重,但有时候也会需要只保留重复值. 这里就简单的介绍一下对于DataFrame去重和取重复值的操作. 创建DataFrame 这里首先创建一个 ...

  4. python duplicated函数_Python DataFrame使用drop_duplicates()函数去重(保留重复值,取重复值)...

    Python DataFrame使用drop_duplicates()函数去重(保留重复值,取重复值) 摘要 在进行数据分析时,我们经常需要对DataFrame去重,但有时候也会需要只保留重复值. 这 ...

  5. python去重保留唯一一个值_Python DataFrame使用drop_duplicates()函数去重(保留重复值,取重复值)...

    摘要 在进行数据分析时,我们经常需要对DataFrame去重,但有时候也会需要只保留重复值. 这里就简单的介绍一下对于DataFrame去重和取重复值的操作. 创建DataFrame 这里首先创建一个 ...

  6. java,url长链接生成短链接,短链接生成器,自定义字符串,对字符串md5混合KEY加密,根据短链接获得key值,不重复的随机数,不重复的随机字符串...

    java,url长链接生成短链接,短链接生成器,自定义字符串,对字符串md5混合KEY加密,根据短链接获得key值,不重复的随机数,不重复的随机字符串 1 package com.zdz.test; ...

  7. 在Excel中怎么筛选唯一值或删除重复值以及对其应用条件格式

    重复值是行中的所有值与另一个行中的所有值完全匹配的值,筛选唯一值时,将临时隐藏重复的值,但删除重复值时,则会永久删除重复值.最好先筛选唯一值或对其应用条件格式,以便在删除重复值之前确认结果是所需的.下 ...

  8. java中hash值什么意思_到底什么是hash?它起什么作用?

    从emule诞生到现在也已经有了两年左右时间了,随着emule的普及,喜欢他的人也越来越多,但是由于网络 从emule诞生到现在也已经有了两年左右时间了,随着emule的普及,喜欢他的人也越来越多,但 ...

  9. python字典中的值不允许重复_python字典中值不允许重复的原因

    python字典中值不允许重复的原因 发布时间:2020-10-29 10:03:21 来源:亿速云 阅读:104 作者:小新 这篇文章给大家分享的是有关python字典中值不允许重复的原因的内容.小 ...

最新文章

  1. tomcat 性能设置
  2. 【题解】P1029 最大公约数和最小公倍数问题
  3. ios 即时聊天轻松搞定
  4. 【Visual Studio 扩展工具】使用ComponentOne中的GroupDefinition和SortDefinition属性保存和还原布局...
  5. 前端每周清单第 49 期:Webpack 4 Beta 尝鲜,React Windowing 与 setState 分析
  6. BurpSuite pro v2.0.11版
  7. 快手直播平台演进之路
  8. LeetCode 1061. 按字典序排列最小的等效字符串(并查集)
  9. LeetCode 427. 建立四叉树(递归)
  10. C#的百度地图开发(一)发起HTTP请求
  11. 旧服务器如何虚拟化,4个步骤教你如何重复利用旧虚拟化主机
  12. 编辑器、编译器和IDE的区别
  13. 合并报表软件系统推荐
  14. 服务器硬件上架安装步骤,一般服务器上架步骤;
  15. Redis的读写分离
  16. 计算机自动关机原理,电脑自动关机是什么原因怎样处理
  17. Excel技巧:合并单元格后分组排序
  18. 斐波那契数列前20项及和
  19. 超级账本hyperledger fabric第五集:共识排序及源码阅读
  20. 服务器装exi系统_ESXI 6.5安装详细步骤

热门文章

  1. 躁动的小Z 最短路+路径记录
  2. 使用promise解决回调地狱_使用Promise 解决回调地狱
  3. Shiro之权限管理的概念
  4. JAVA——读取文本文件的倒数第N行(模拟Linux中tail命令)
  5. 湖南大学第十五届程序设计竞赛
  6. arcscene如何显示标注_CAD制图初学入门:CAD制图软件中如何添加多重标注?
  7. WordPress上传大小限制问题
  8. 英语作文万能句子总结版
  9. Android EventBus 3.0.0 使用总结
  10. Xcode 6制作动态及静态Framework