字符串哈希,帮您解决记不住kmp的烦恼~

2023-11-06

//思想,把字符串映射为哈希值,通过哈希值就可以定位唯一字符串,可以某种程度上替代kmp,而且比kmp好理解好记忆

        //字符串hash模板
        int P = 131; // 或者13331 经验值
        String s = "hello";
        int n = s.length();
        long[] h = new long[n + 1], p = new long[n + 1];
        p[0] = 1;
        //计算出模板的h,p值
        for (int i = 1; i <= n; i++) {
            h[i] = h[i] * P + s.charAt(i);
            p[i] = p[i - 1] * P;
        }
        //此时任意的字符串都可以利用h,p进行映射 如L - R;
        // h[L - R] = h[R] - h[L - 1] * p[R - L + 1],证明随便找几个串试试即可
        //such as 寻找hello中的ll 则L = 3, R = 4
        int len = 2, L = 3, R = 4;
        long hash = h[4] - h[L - 1] * p[R - L + 1];//这就是ll对应的哈希值可以快速查找ll

//如果您想推导可以像上图!~

//不废话了我们来做几题试试吧!

1.先来试试替换kmp?当然面试可以写字符串哈希

 

//传统解法肯定是kmp,但是我们可以看到有重复串的查找,尝试字符串哈希
public int strStr(String haystack, String needle) {
        if(needle == "" || haystack == "") return 0;
        int P = 131;//经验值
        int n = haystack.length();
    	//模板
        int[] h = new int[n + 1], p = new int[n + 1]; 
        p[0] = 1;
        for(int i = 1; i <= n; i ++){
            h[i] = h[i - 1] * P + haystack.charAt(i - 1); //把heystack中的字符串进行映射
            p[i] = p[i - 1] * P;
        }
        int hash = 0;
        for(int i = 0; i < needle.length(); i ++){
            hash = hash * P + needle.charAt(i);  //把needle中的值算出来,因为是计算全部所以不需要p数组
        }											//因为h[L - 1] = h[0] = 0后面没了
        for(int i = 1; i <= n - needle.length() + 1; i ++){
    //我们从左边开始遍历,容易知道L = i, R = i + needle.length() - 1,套用模板可以枚举出he,el,ll,lo,o(n)时间复杂度
            int Hash = h[i + needle.length() - 1] - h[i - 1] * p[needle.length()];
            if(Hash == hash) return i - 1;   //注意这边映射成了1-n,所以返回的时候要下标-1
        }
        return -1; 
    }

2.什么kmp你觉得不满足?那咱们来一道字节一面二面出的概率较高的困难?我看的面经中遇到十次以上了所以来试试吧!

 

//先分析一下思路,最长重复串的话,那我们考虑重复可以利用字符串哈希去预处理哈希值找是否有重复的哈希值	
	//最长的话简单想到暴力1-2-3一个一个尝试那么会超时,那怎么样找最长?->二分咋样?
	//这边给小伙伴们一个思路,通常整个数组中找最长最短且需要验证的题目一般是二分+验证可以nlogn,如果你不信可以去力扣周赛找找挺多的这种题,好啦不废话了我们开始
	long P = 13331;
    long[] h, p;
    public String longestDupSubstring(String s) {
        int n = s.length();
        //模板先整起来
        h = new long[n + 1]; p = new long[n + 1];
        p[0] = 1;
        for(int i = 1; i <= n; i ++){
            h[i] = h[i - 1] * P + s.charAt(i - 1);
            p[i] = p[i - 1] * P;
        }
        int l = 1, r = s.length() - 1;
        String ans = "";
        while(l <= r){
            int mid = (l + r) >> 1;
            //这边就是验证最长的过程
            String t = check(mid, s);
            if(t != "") {
                //记录答案
                ans = t;
                l = mid + 1;
            }
            else r = mid - 1;
        }
        return ans; //诶好像就结束了是不是有点简单?当然本题可以利用kmp,但是我也记不住kmp,忘了好几次了放弃了。
    }
    public String check(int len, String s){
        //这边我们需要找到重复的哈希值,那就利用set来记录是否有重复,当然你也可用map
        Set<Long> set = new HashSet<>();
        for(int i = 1; i <=  s.length() - len + 1; i ++){
            //从1开始,因为我们已经二分了长度所以 R = i + len - 1, L = i - 1 
            long hash = h[i + len - 1] - h[i - 1] * p[len]; 
      //举个例子len = 3,s=banana,这边就是计算出ban,ana,nan,ana的哈希值,然后放到set里面,set有重复证明重新出现过合法
            if(set.contains(hash)) return s.substring(i - 1, i - 1 + len);
            set.add(hash);
        }
        return "";
    }

3.最后再来一题吧?思路更简单了你可以自己尝试一下

 

//思路:诶你自己肯定没去试试,好吧我带你做,这边呢就是找有没有连接字符串,那我们连接字符串拆开是不是就是两个一样的哈希值了?
//那我们可以预处理一下哈希值,然后枚举字符串(这边因为利用了字符串哈希所以比较两个字符串可以达到O(1)的复杂度)那就简单了啦~
public int distinctEchoSubstrings(String text) {
        int P = 131;
        int n = text.length();
        Set<Integer> set = new HashSet<>();
    	//模板
        int[] h = new int[n + 1], p = new int[n + 1];  
        p[0] = 1;
        for(int i = 1; i <= n; i ++){
            h[i] = h[i - 1] * P + text.charAt(i - 1);
            p[i] = p[i - 1] * P;
        }   
        for(int i = 1; i <= n; i ++){
            for(int j = i + 1; j <= n; j += 2){
                //枚举分成两个
                int len = (j - i + 1) / 2; 
                int hash1 = h[j] - h[j - len] * p[len]; //左边那一半
                int hash2 = h[j - len] - h[i - 1] * p[len]; //右边那一半 相等就合法
                if(hash1 == hash2 && !set.contains(hash1)){
                    set.add(hash1);
                }
            }
        }
        return set.size();
    }

总结:1.可以代替kmp解决问题 2.模板好记忆 3.适用于重复xxxx的字符串问题

好啦今天的小讲堂就到这里啦,希望你能够把字符串哈希学会,说不定面试还能给面试官秀一手,当然最关键的还是他能够替代kmp,而且更简单记忆更好写,这个模板不难背吧?当然给你留到作业吧!力扣1392 hard,看看你能不能学以致用亲自解决一道hard呢?加油哦!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

字符串哈希,帮您解决记不住kmp的烦恼~ 的相关文章

  • Java 线程何时达到“死亡”状态

    在 Java 中 Die 是线程的状态之一 什么原因导致线程进入这种状态 来自线程API http java sun com javase 6 docs api java lang Thread html 这是一个完整的列表 如果 run
  • Gson - 使用两个不同的键读取值

    在我的 Android 项目中 我有两种类型的响应除了两个键之外 响应是相同的 回应1 fullName William Sherlock Scott Holmes address 221B Baker Street London Engl
  • 在Android的IntentService中等待异步回调

    我有一个IntentService在另一个类中启动异步任务 然后等待结果 问题是IntentService将尽快完成onHandleIntent 方法已经运行完毕了 对吗 这意味着 通常情况下 IntentService异步任务启动后会立即
  • setUserVisibleHint 中的空上下文

    当 ViewPager 中的片段变得可见时 需要向用户显示一条消息 目前的通话是 Within a class that extends Fragment Override public void setUserVisibleHint bo
  • 如何为 Runnable 分配方法引用值

    我有一个关于 Java 8 的问题Runnable public static void main String args Runnable r1 Test t1 Runnable r2 Test t2 Runnable r3 Test t
  • 使用 Smack 库解析 XMPP 的 EventElement

    任何人都可以帮助向我展示如何解析此事件 pub 元素并获取以下数据包的消息对象 也许我的关键字 搜索词谷歌搜索不正确 但我在寻找有关此问题的文档或教程时找不到任何有用的东西 我读过一些有关 PacketParserUtils 和 XmlPu
  • 如何格式化 LocalTime 变量

    我对 Java windowbuilder 很陌生 这是我第一个项目的一部分 String starttime JOptionPane showInputDialog null What time would you like to sta
  • 如何以编程方式在锁定屏幕上设置快捷方式[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我知道如何在主屏幕上设置快捷方式 但不知道如何在锁定屏幕上设置快捷方式 有任何想法吗 很少有 Android 设备具有支持快捷方式的锁
  • Java 的 3D 场景图库?

    我正在寻找一个可靠的 Java 3D 场景图 API 它具有良好的文档 活跃的社区和允许商业使用的许可证 我排除了com sun scenegraph https scenegraph dev java net 因为它是 GPL 而且看起来
  • Jackson @JsonUnwrapped 行为与自定义 JsonSerializer

    我有两个这样的课程 public class A String aProp aProp public String getAProp return aProp public class B String bProp bProp A a ne
  • javax.net.ssl.SSLHandshakeException

    最近 我们的一个 Java 应用程序遇到了问题 该应用程序试图运行受 SSL 保护的 amazone 负载均衡器 Web 服务 该服务的证书由 GoDaddy 签名 我们没有将公钥证书链文件 PEM 编码 的内容复制并粘贴到 证书链 框中
  • 如何正确处理 JWT 刷新?

    我有一个安卓应用程序 它连接到一个REST API开发与Jersey 我的 REST 端点通过令牌进行保护 下面是我生成它们的方法 Algorithm algorithm Algorithm HMAC256 secret String to
  • Elasticsearch:在 java.lang.OutOfMemoryError:Java 堆空间后重新启动节点

    我的一个 ES 节点失败了 因为java lang OutOfMemoryError Java heap space错误 这是日志中的完整堆栈跟踪 2020 09 18T04 25 04 215 WARN o e a b Transport
  • 在多线程环境下使用JUnit的奇怪问题

    在多线程环境中使用 JUnit 时 我遇到一个奇怪的问题 下面的代码应该会失败 但在eclipse中却确实通过了 public class ExampleTest extends TestCase private ExecutorServi
  • 使用 jni 从 C 调用 java 函数

    我正在编写一个简单的程序来从我的 C 程序调用 Java 函数 以下是我的代码 include
  • 如何在 Java 中使用 JsonPath 从 JSON 获取值?

    我想使用 JsonPath 从 JSON 对象中获取值 任何人都可以建议我我需要的适当的 jar 因为据我所知 我在用于 jsonpath 的 jar 中遇到了此异常 package jsonPg import java io IOExce
  • 我们如何在Android中动态更改Android应用程序图标[重复]

    这个问题在这里已经有答案了 我知道活动图标也被问过同样的问题 但我的问题有点不同 我只是想知道我们是否可以以编程方式设置应用程序图标 我不是要求更改 我只是要求设置它 我希望我说清楚了
  • 注释非法 Unicode 序列

    我曾经在一个处理 unicode 处理的 Java 应用程序上工作 像往常一样 我首先编写一些代码并测试它 然后注释掉工作代码并添加一些新行 这个过程一直持续到我找到解决方案 我遇到的确切问题是注释掉非法的 Unicode 字符串 有些 u
  • 此内存使用模式是否表明我的 Java 应用程序泄漏了内存?

    我有一个 Java 应用程序 它等待用户按键然后运行任务 一旦完成 它就会返回并再次等待 我正在使用 jvisualvm 查看此应用程序的内存配置文件 它显示出不断增加的模式 承诺内存大小为 16MB 应用程序启动时使用的内存为 2 7 M
  • Morphia - 未在 dbObj 中找到定义的类

    我有一个相当有趣的问题 当尝试从 Mongo 实例加载模型时 Morphia 会抛出以下错误 22 17 13 WARN Class not found defined in dbObj java lang ClassNotFoundExc

随机推荐

  • STM32的DMA输出DAC的正弦波与三角波 幅度与周期可调可调(原创篇);

    废话不多说 因为激光振镜驱动需要正弦波与三角波 为了省事 直接通过STM32F407实现DAC的DMA输出 省CPU资源 经过调试 在0 NkHZ之内都可以实现 目前采样点为500个 上数据吧 其中三角波自动生成500个数据 在初始化的时候
  • 自己的Anaconda管理多个虚拟环境,这样就可以在不同的环境下安装互不干扰的库

    项目场景 Anaconda可以安装多个虚拟解释器 每个解释器可以安装自己独有的库 从而每个解释器之间起到互不干扰的作用 这点Anaconda就非常强大了 查看Anaconda的解释环境 在电脑开始中选择Anaconda Prompt set
  • 搭建一个vue3+ts项目(超祥/必看)

    一 创建vite项目 1 在一个文件夹下通过cmd打开 输入命令 npm create vite latest 2 接着选择ts 3 创建好之后 结构目录如下 二 启动vite项目 1 安装依赖 启动项目前需要先 npm i 从上图可以发现
  • C++智能指针知识总结

    智能指针 智能指针是为了避免内存泄漏的技术 智能指针采用了RAII特性 利用对象生命周期来控制程序资源 在对象构造时获取资源 接着控制对资源的访问使之在对象的生命周期内始终保持有效 最后在对象析构的时候释放资源 借此 我们实际上把管理一份资
  • Python 四五事

    介绍 Python 相关工具 工作流程和测试框架 最后更新 2014 1 19 引言 接续着之前的文章 虽然隔得比较久 本文继续介绍以 Windows 平台为背景的 Python 开发相关的工具 希望能对你有所帮助 另外很多东西本文都是延续
  • html+css+javascript知识点总结

    一 html css 基础 1 1 Html 和 CSS 的关系 学习 web 前端开发基础技术需要掌握 HTML CSS JavaScript 语言 下面我们就来了解下这三门技术都是用来实现什么的 1 HTML 是网页内容的载体 内容就是
  • 14.12 修改职工信息

    14 12 修改职工信息 1 按照编号修改职工信息 先声明 修改职工 void mod Emp 再实现 就是把查到的职工删除 再在那个位置输入一个新职工 所以跟添加职工的代码很多地方一样 修改职工 void WorkerManager mo
  • Koordinator 异构资源/任务调度实践

    前言 Koordinator 是阿里云基于过去我们建设的统一调度系统中积累的技术和实践经验 对外开源了新一代的调度系统 Koordinator 支持 Kubernetes 上多种工作负载的混部调度 它的目标是提高工作负载的运行时效率和可靠性
  • 从入门到放弃系列--如何成为全栈工程师04

    之前的3节课 我告诉了你基础的html div css布局 你应该已经了解网页是怎么制作的 在开从第5节课开始 我会用一个完整的实例 带你制作快速制作一个企业网站 这节课 我要把让你明白 当你在浏览器里输入一个网址 网页是怎么出现的 以及
  • 数据分析与数据挖掘的区别

    数据分析 数据分析是用适当的统计方法对收集的数据进行分析 概括 总结 对数据进行恰当的描述 提取有用的信息 数据挖掘 数据挖掘是从海量的数据中通过算法发现隐藏在数据中的规律和知识的过程 区别 1 数据分析数据量可大可小 数据挖掘需要从海量数
  • 重磅:门头沟赔偿推迟5个月,没有无缘无故的大涨!

    Mt Gox善后受托人向东京地方法院提出寻求延长善后计划提交期限的动议 2019年10月25日 东京地方法院发布一项命令 允许延长期限到2020年3月31日提交善后计划 编译 白夜 编辑 秦晋 碳链价值最新获悉 Mt Gox发布声明表示 由
  • Python3中Pillow(PIL)介绍

    PIL全称为Python Imaging Library 是Python中的免费开源图像处理库 PIL的最新版本为1 1 7 于2009年9月发布 支持Python的最高版本到2 7 原始的PIL开发于2011年停止 随后 一个名为Pill
  • vue前端实现模糊查询然后表格自动定位

    element input自动补全输入框 el table 注 这个table没有做分页 数据又多 所以才在前端添加搜索定位功能 html 自动补全输入框 和 table
  • 浏览器的标准模式、怪异模式

    历史原因 在W3C标准未确定之前 各浏览器对于HTML和CSS有各自不同的解析方式 很多旧网页都是在W3C标准未确定时期实现 设计的 在W3C标准确定之后 浏览器为了保证对非标准的旧网页设计的后向兼容性 现代浏览器 IE6以上 IE6以下版
  • ORACLE UNION和UNION ALL操作符

    UNION用于合并两个及以上查询结果 SELECT COLUMN1 FROM TABLE1 UNION ALL SELECT COLUMN2 FROM TABLE2 其中COLUMN1和COLUMN2的数量 顺序相同 数据类型要相似 UNI
  • 线程破解程序死循环

    最近用opencv mfc做了一个简单的程序 点击button后 打开视频 另一个button关闭视频 问题来了 读视频的程序是个死循环 怎么解 因此 应该考虑线程的问题了 让视频程序在线程里跑 何为线程 线程 有时被称为轻量级进程 Lig
  • win10系统上的mysql服务器,win10查看mysql服务器配置

    win10查看mysql服务器配置 内容精选 换一换 本篇文章是关于在win10 win7 winxp中 相对偏技术员的一些快捷键介绍 例如regedit进入注册表的快捷键 以及进入cmd的命令行快捷键 推荐下载 win10专业版系统在wi
  • Java数据结构——平衡二叉树(AVL树)

    AVL树的引入 搜索二叉树有着极高的搜索效率 但是搜索二叉树会出现以下极端情况 这样的二叉树搜索效率甚至比链表还低 在搜索二叉树基础上出现的平衡二叉树 AVL树 就解决了这样的问题 当平衡二叉树 AVL树 的某个节点左右子树高度差的绝对值大
  • 蚂蚁感冒 (acwing)

    文章目录 蚂蚁感冒 思路 AC代码 蚂蚁感冒 长 100 厘米的细长直杆子上有 n 只蚂蚁 它们的头有的朝左 有的朝右 每只蚂蚁都只能沿着杆子向前爬 速度是 1 厘米 秒 当两只蚂蚁碰面时 它们会同时掉头往相反的方向爬行 这些蚂蚁中 有 1
  • 字符串哈希,帮您解决记不住kmp的烦恼~

    思想 把字符串映射为哈希值 通过哈希值就可以定位唯一字符串 可以某种程度上替代kmp 而且比kmp好理解好记忆 字符串hash模板 int P 131 或者13331 经验值 String s hello int n s length lo