【滚动哈希 二分查找】1044. 最长重复子串
本文涉及知识点
滚动哈希
二分查找算法合集
LeetCode 1044. 最长重复子串
给你一个字符串 s ,考虑其所有 重复子串 :即 s 的(连续)子串,在 s 中出现 2 次或更多次。这些出现之间可能存在重叠。
返回 任意一个 可能具有最长长度的重复子串。如果 s 不含重复子串,那么答案为 “” 。
示例 1:
输入:s = “banana”
输出:“ana”
示例 2:
输入:s = “abcd”
输出:“”
提示:
2 <= s.length <= 3 * 104
s 由小写英文字母组成
二分查找+滚动哈希
令 Check(len) 返回 是否存在长度为len的重复字符串
len1 < len2,如果Check(len2)为true,则Check(len1)一定为true
即 len ∈ \in ∈ [0,len3]为Check(len)为true,len ∈ \in ∈ [len3+1,n] Check(len)为false。
寻找最后一个true,故用左闭右开空间。
Check函数
len = 0 为0,返回true。
用滚动函数计算 s[i…i+len-1]的哈希值, i+ len <= s.length 并将哈希值记录到set中,如果存在重复值,返回true。
时间复杂度:O(nlogn)
二分查找:O(logn) Check函数O(n)
代码
核心代码
template<int MOD = 1000000007>
class C1097Int
{
public:C1097Int(long long llData = 0) :m_iData(llData% MOD){}C1097Int operator+(const C1097Int& o)const{return C1097Int(((long long)m_iData + o.m_iData) % MOD);}C1097Int& operator+=(const C1097Int& o){m_iData = ((long long)m_iData + o.m_iData) % MOD;return *this;}C1097Int& operator-=(const C1097Int& o){m_iData = (m_iData + MOD - o.m_iData) % MOD;return *this;}C1097Int operator-(const C1097Int& o){return C1097Int((m_iData + MOD - o.m_iData) % MOD);}C1097Int operator*(const C1097Int& o)const{return((long long)m_iData * o.m_iData) % MOD;}C1097Int& operator*=(const C1097Int& o){m_iData = ((long long)m_iData * o.m_iData) % MOD;return *this;}C1097Int operator/(const C1097Int& o)const{return *this * o.PowNegative1();}C1097Int& operator/=(const C1097Int& o){*this /= o.PowNegative1();return *this;}bool operator==(const C1097Int& o)const{return m_iData == o.m_iData;}bool operator<(const C1097Int& o)const{return m_iData < o.m_iData;}C1097Int pow(long long n)const{C1097Int iRet = 1, iCur = *this;while (n){if (n & 1){iRet *= iCur;}iCur *= iCur;n >>= 1;}return iRet;}C1097Int PowNegative1()const{return pow(MOD - 2);}int ToInt()const{return m_iData;}
private:int m_iData = 0;;
};//iCodeNum 必须大于等于可能的字符数
template<int MOD = 1000000007>
class CHashStr {
public:CHashStr(string s, int iCodeNum, int iCodeBegin = 1, char chBegin = 'a') {m_c = s.length();m_vP.resize(m_c + 1);m_vP[0] = 1;m_vHash.resize(m_c + 1);for (int i = 0; i < m_c; i++){const int P = iCodeBegin + iCodeNum;m_vHash[i + 1] = m_vHash[i] * P + s[i] - chBegin + iCodeBegin;m_vP[i + 1] = m_vP[i] * P;}}//iMinValue将被编码为0,iMaxValue被编码为iMaxValue-iMinValue。CHashStr(const int* data, int len, int iMinValue = 0, int iMaxValue = 9) {m_c = len;m_vP.resize(m_c + 1);m_vP[0] = 1;m_vHash.resize(m_c + 1);const int P = iMaxValue - iMinValue + 1;for (int i = 0; i < m_c; i++){const int iCurCode = data[i] - iMinValue;assert((iCurCode >= 0) && (iCurCode < P));m_vHash[i + 1] = m_vHash[i] * P + iCurCode;m_vP[i + 1] = m_vP[i] * P;}}//包括left rightint GetHash(int left, int right){return (m_vHash[right + 1] - m_vHash[left] * m_vP[right - left + 1]).ToInt();}inline int GetHash(int right){return m_vHash[right + 1].ToInt();}int GetHashExincludeRight(int left, int right){return (m_vHash[right] - m_vHash[left] * m_vP[right - left]).ToInt();}inline int GetHashExincludeRight(int right){return m_vHash[right].ToInt();}int m_c;vector<C1097Int<MOD>> m_vP;vector<C1097Int<MOD>> m_vHash;
};template<int MOD2 = 1000000009>
class C2HashStr
{
public:C2HashStr(string s) {m_pHash1 = std::make_unique<CHashStr<>>(s, 26);m_pHash2 = std::make_unique < CHashStr<MOD2>>(s, 27, 0);}C2HashStr(const int* data, int len, int iMinValue = 0, int iMaxValue = 9){m_pHash1 = std::make_unique<CHashStr<>>(data, len, iMinValue, iMaxValue);m_pHash2 = std::make_unique < CHashStr<MOD2>>(data, len, iMinValue, iMaxValue);}//包括left rightlong long GetHash(int left, int right){return (long long)m_pHash1->GetHash(left, right) * (MOD2 + 1) + m_pHash2->GetHash(left, right);}long long GetHash(int right){return (long long)m_pHash1->GetHash(right) * (MOD2 + 1) + m_pHash2->GetHash(right);}//包括Left,不包括Rightlong long GetHashExincludeRight(int left, int right){return (long long)m_pHash1->GetHashExincludeRight(left, right) * (MOD2 + 1) + m_pHash2->GetHashExincludeRight(left, right);}long long GetHashExincludeRight(int right){return (long long)m_pHash1->GetHashExincludeRight(right) * (MOD2 + 1) + m_pHash2->GetHashExincludeRight(right);}
private:std::unique_ptr<CHashStr<>> m_pHash1;std::unique_ptr<CHashStr<MOD2>> m_pHash2;
};namespace NBinarySearch
{template<class INDEX_TYPE, class _Pr>INDEX_TYPE FindFrist(INDEX_TYPE left, INDEX_TYPE rightInclue, _Pr pr){while (rightInclue - left > 1){const auto mid = left + (rightInclue - left) / 2;if (pr(mid)){rightInclue = mid;}else{left = mid;}}return rightInclue;}template<class INDEX_TYPE, class _Pr>INDEX_TYPE FindEnd(INDEX_TYPE leftInclude, INDEX_TYPE right, _Pr pr){while (right - leftInclude > 1){const auto mid = leftInclude + (right - leftInclude) / 2;if (pr(mid)){leftInclude = mid;}else{right = mid;}}return leftInclude;}
}class Solution {
public:string longestDupSubstring(string s) {string ret;C2HashStr<> dh(s);auto Check = [&](int len) {if (0 == len) { ret = ""; return true; }unordered_set<long long> setHas;for (int i = 0; i + len <= s.length(); i++) {auto cur = dh.GetHashExincludeRight(i, i + len);if (setHas.count(cur)) {ret = s.substr(i, len);return true;}setHas.emplace(cur);}return false;};NBinarySearch::FindEnd(0, (int)s.length() + 1, Check);return ret;}
};
单元测试
template<class T1,class T2>
void AssertEx(const T1& t1, const T2& t2)
{Assert::AreEqual(t1 , t2);
}template<class T>
void AssertEx(const vector<T>& v1, const vector<T>& v2)
{Assert::AreEqual(v1.size(), v2.size()); for (int i = 0; i < v1.size(); i++){Assert::AreEqual(v1[i], v2[i]);}
}template<class T>
void AssertV2(vector<vector<T>> vv1, vector<vector<T>> vv2)
{sort(vv1.begin(), vv1.end());sort(vv2.begin(), vv2.end());Assert::AreEqual(vv1.size(), vv2.size());for (int i = 0; i < vv1.size(); i++){AssertEx(vv1[i], vv2[i]);}
}namespace UnitTest
{string s;TEST_CLASS(UnitTest){public:TEST_METHOD(TestMethod1){s = "banana";auto res = Solution().longestDupSubstring(s);AssertEx(string("ana"), res);}TEST_METHOD(TestMethod2){s = "abcd";auto res = Solution().longestDupSubstring(s);AssertEx(string(""), res);}TEST_METHOD(TestMethod3){s = "aa";auto res = Solution().longestDupSubstring(s);AssertEx(string("a"), res);} };
}

扩展阅读
视频课程
先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176
相关推荐
| 我想对大家说的话 |
|---|
| 《喜缺全书算法册》以原理、正确性证明、总结为主。 |
| 按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。 |
| 有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注 |
| 闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 |
| 子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
| 如果程序是一条龙,那算法就是他的是睛 |
测试环境
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

相关文章:
【滚动哈希 二分查找】1044. 最长重复子串
本文涉及知识点 滚动哈希 二分查找算法合集 LeetCode 1044. 最长重复子串 给你一个字符串 s ,考虑其所有 重复子串 :即 s 的(连续)子串,在 s 中出现 2 次或更多次。这些出现之间可能存在重叠。 返回 任意一个 可能具…...
webid、sec_poison_id、a1、web_session参数分析与算法实现
文章目录 1. 写在前面2. 参数分析3. 核心算法【🏠作者主页】:吴秋霖 【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python与爬虫领域研究与开发工作! 【🌟作者推荐】:对爬…...
Qt|QWebSocket与Web进行通讯,实时接收语音流
实现功能主要思路:在网页端进行语音输入,PC机可以实时接收并播放语音流。 此时,Qt程序做客户端,Web端做服务器,使用QWebSocket进行通讯,实时播放接收的语音流。 功能实现 想要实现该功能,需要…...
「51媒体」电视台媒体邀约采访报道怎么做?
传媒如春雨,润物细无声,大家好,我是51媒体网胡老师。 电视台作为地方主流媒体,对于新闻报道有着严格的选题标准和报道流程。如果您希望电视台对某个会议或活动进行报道,可以按这样的方法来做: 1.明确活动信…...
Python提取PDF文本和图片,以及提前PDF页面中指定矩形区域的文本
前言 从PDF中提取内容能帮助我们获取文件中的信息,以便进行进一步的分析和处理。此外,在遇到类似项目时,提取出来的文本或图片也能再次利用。要在Python中通过代码提取PDF文件中的文本和图片,可以使用 Spire.PDF for Python 这个…...
C#实现边缘锐化(图像处理)
在 C# 中进行图像的边缘锐化,可以通过卷积滤波器实现。边缘锐化的基本思想是通过卷积核(也称为滤波器或掩模)来增强图像中的边缘。我们可以使用一个简单的锐化核,例如: [ 0, -1, 0][-1, 5, -1][ 0, -1, 0]这个卷积核…...
ffmpeg windows系统详细教程
视频做预览时黑屏,但有声音问题解决方案。 需要将 .mp4编成H.264格式的.mp4 一般上传视频的站点,如YouTube、Vimeo 等,通常会在用户上传视频时自动对视频进行转码,以确保视频能够在各种设备和网络条件下流畅播放。这些网站通常…...
【单片机】MSP430G2553单片机 Could not find MSP-FET430UIF on specified COM port 解决方案
文章目录 MSP430G2553开发板基础知识解决办法如何实施解决办法4步骤一步骤二步骤三 MSP430G2553开发板基础知识 MSP430G2553开发板如下图,上半部分就是UIF程序下载调试区域的硬件。个人觉得MSP430G2553开发板的这个部分没有做好硬件设计,导致很多系统兼…...
每日一题——力扣104. 二叉树的最大深度(举一反三+思想解读+逐步优化)四千字好文
一个认为一切根源都是“自己不够强”的INTJ 个人主页:用哲学编程-CSDN博客专栏:每日一题——举一反三Python编程学习Python内置函数 目录 我的写法 代码功能 代码结构 时间复杂度分析 空间复杂度分析 总结 我要更强 优化方法:迭代&…...
wpf textbox 有焦点 导致后台更新 前台不跟着改变
这个问题可能是由于 WPF 的数据绑定机制导致的。当 TextBox 有焦点时,它会独立于数据绑定进行更新,这可能会导致前台界面不能及时反映后台数据的变化。 1.使用 UpdateSourceTrigger 属性: 在数据绑定时,将 UpdateSourceTrigger 属性设置为 PropertyChanged。这样当 TextBox 的…...
数字化物资管理系统的未来:RFID技术的创新应用
在信息化和智能化不断发展的背景下,物资管理系统的数字化转型已成为各行各业关注的焦点。RFID技术作为一种先进的物联网技术,通过全面数字化实现物资信息的实时追踪和高效管理,为企业的物资管理提供了强有力的支持。 首先,RFID技…...
【docker】常用指令-表格整理
以下列出的指令是Docker中常用的命令,但并不是全部。Docker的指令非常丰富,可以根据具体的需求和场景选择合适的指令。同时,每个指令都有很多选项和参数可以使用,可以通过 docker COMMAND --help 来获取更详细的信息。 一、容器命…...
洛谷——P2824 排序
题目来源:[HEOI2016/TJOI2016] 排序 - 洛谷https://www.luogu.com.cn/problem/P2824 问题思路 本文介绍一种二分答案的做法,时间复杂度为:(nm)*log(n)*log(n).本题存在nlog(n)的做法,然而其做法没有二分答案的做法通俗易懂. 默认读…...
echart在线图表demo下载直接运行
echart 全面的数据可视化图表解决方案 | 折线图、柱状图、饼图、散点图、水球图等各类图表展示 持续更新中 三色带下表题速度仪表盘 地图自定义图标 动态环形图饼状图 动态水波动圆形 多标题指针仪表盘 温度仪表盘带下标题 横向柱状图排名 环形饼状图 双折线趋势变化...
MLX5_SET_TO_ONES宏解析
看代码时,遇到一个非常复杂的宏MLX5_SET_TO_ONES,这个宏的主要作用是对特定的数据结构置位,宏的上下文如下: #define __mlx5_nullp(typ) ((struct mlx5_ifc_##typ##_bits *)0) #define __mlx5_bit_off(typ, fld) (offsetof(struc…...
SQL Server入门-SSMS简单使用(2008R2版)-1
环境: win10,SQL Server 2008 R2 参考: SQL Server 新建数据库 - 菜鸟教程 https://www.cainiaoya.com/sqlserver/sql-server-create-db.html 第 2 课:编写 Transact-SQL | Microsoft Learn https://learn.microsoft.com/zh-cn/…...
高考专业抉择探索计算机专业的未来展望及适合人群
身份:一位正在面临人生重要抉择的高考生,一位计算机行业从业者 正文: 随着2024年高考落幕,我与数百万高三学生一样,又将面临人生中的重要抉择:选择大学专业。对于许多学生来说,计算机科学…...
windows安装spark
在 Windows 上安装 Spark 并进行配置需要一些步骤,包括安装必要的软件和配置环境变量。以下是详细的步骤指南: 步骤一:安装 Java 下载和安装 Java Development Kit (JDK) 到 Oracle JDK 下载页面 或 OpenJDK 下载页面 下载适合你系统的 JDK。…...
【信息学奥赛】CSP-J/S初赛03 计算机网络与编程语言分类
第1节 计算机网络基础 1.1 网络的定义 所谓计算机网络,就是利用通信线路和设备,把分布在不同地理位置上的多台计算机连 接起来。计算机网络是现代通信技术与计算机技术相结合的产物。 网络中计算机与计算机之间的通信依靠协议进行。协议是计算机收、发…...
python20 函数的定及调用
函数的定及调用 函数是将一段实现功能的完整代码,使用函数名称进行封装,通过函数名称进行调用。以此达到一次编写,多次调用的目的 用 def 关键字来声明 函数 格式: def 函数名(参数列表):函数体[:return 返回值是可选的࿰…...
无王无帝定乾坤,来自田间第一人 凰标重塑新风骨
一、破题:王权不是答案旧认知新真相山河气运系于帝王扭转乾坤藏于民间位高者裁定是非布衣亦可定乾坤权贵定义风骨凰标重塑精神二、旧世风骨之殇等级枷锁 王权为纲 → 尊卑为界 → 精神镣铐千年。世俗偏见 财富分贵贱 → 地位论高低 → 人心逐利忘本。结局 风骨消磨 …...
性能优化必看:你的Unity粒子特效为什么这么卡?从ParticleSystem参数入手排查
Unity粒子特效性能优化实战指南:从参数调优到帧率提升 1. 粒子特效性能问题的根源剖析 在移动端和VR项目中,粒子特效往往是性能瓶颈的重灾区。一次性能审计中,某款手游的瀑布场景因未限制粒子最大数量,导致中端机型帧率骤降至18fp…...
别焦虑,也别躺平:给年轻程序员的一封信
2026年了,程序员这个行业,和前几年的感觉已经完全不一样了。以前大家更多的是在想: 谁会的框架多谁加班狠谁能把CRUD写得飞快 现在很多东西,AI十几秒就能生成。不少年轻程序员开始焦虑: “以后是不是不需要程序员了&am…...
【新手向】:OpenClaw 本地 AI 智能体 Windows 部署教程(包含安装包)
Windows 一键部署 OpenClaw 教程|5 分钟搞定本地 AI 智能体,告别复杂配置 2026 年开源圈备受关注的「数字员工」OpenClaw(昵称小龙虾),凭借本地运行 零代码操作 自动执行任务的核心优势,成为实用型本地 …...
性能优化实战:在Unity项目里管理多个Video Player,如何避免内存泄漏和卡顿?
Unity多视频管理实战:规避内存泄漏与卡顿的深度优化策略 在沉浸式游戏体验和交互式AR/VR应用中,视频内容已成为提升用户参与度的关键要素。但当场景中同时存在多个Video Player组件时,开发者往往会遭遇突如其来的性能断崖——内存占用飙升、播…...
别再傻傻用FFT了!用MATLAB的czt函数5分钟搞定频谱细化,精准定位98Hz和99Hz信号
别再被FFT分辨率坑了!MATLAB工程师的频谱细化实战指南 当你在分析一段包含98Hz和99Hz混合信号的频谱时,是否遇到过这样的尴尬:明明知道有两个频率成分存在,但FFT给出的结果却像被打了马赛克,两个峰值糊成一团…...
实战剖析:利用Fluxion构建WiFi钓鱼热点与密码捕获
1. 环境准备与工具安装 在开始使用Fluxion进行WiFi安全测试之前,我们需要确保具备合适的硬件和软件环境。首先,你需要一台支持监听模式的无线网卡,这是进行任何无线安全测试的基础硬件。我推荐使用RTL8812AU芯片的网卡,实测下来兼…...
ESJsonFormat-Xcode泛型支持:Xcode 7及以上版本的优化特性
ESJsonFormat-Xcode泛型支持:Xcode 7及以上版本的优化特性 【免费下载链接】ESJsonFormat-Xcode 将JSON格式化输出为模型的属性 项目地址: https://gitcode.com/gh_mirrors/es/ESJsonFormat-Xcode 如果你是一位iOS开发者,那么你一定遇到过将JSON数…...
Bilibili-Evolved:打造无网络依赖的哔哩哔哩增强体验技术解析
Bilibili-Evolved:打造无网络依赖的哔哩哔哩增强体验技术解析 【免费下载链接】Bilibili-Evolved 强大的哔哩哔哩增强脚本 项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved 在当今网络环境复杂多变的时代,用户对Web应用的稳定性要…...
MindStudio组合技,让Host Bound问题看得见、调得准
背景介绍:Host Bound问题在NPU训练和推理场景中,Host侧(CPU)的任务下发(如算子调度、内存分配)与Device侧(NPU)的任务执行是异步进行的。当Host侧任务下发耗时超过Device侧任务执行耗…...
