模式串匹配和字符串哈希

news2025/1/19 8:08:02

目录

一、字符串暴力匹配

二、字符串哈希解决匹配问题

不使用哈希的递归版本

使用哈希的版本

 


不太懂哈希表的可以看我上一篇文章。

哈希表及其基础(java详解)-CSDN博客

一、字符串暴力匹配

public class SubstringMatch {
    //构造函数设置成私有的,不会被创建对象
    private SubstringMatch(){}
    //暴力匹配 源字符串s和目标字符串t
    //在s中寻找t,返回匹配到的第一个索引i,没找到就返回-1
    public static int bruteforce(String s, String t) {
        if (s.length() < t.length()) {
            return -1;
        }
        //s[i, i + t.length - 1] == t ?
        for (int i = 0; i + t.length() - 1 < s.length(); i++) {
            int j = 0;
            for (; j < t.length(); j++) {
                if (s.charAt(i + j) != t.charAt(j))
                    break;
                if (j == t.length() - 1) return i; // 修改这里
            }
        }
        return -1;
    }

    public static void main(String[]args){
        String s1 = "hello, yujing.";
        String t1 = "yujing";
        System.out.println(SubstringMatch.bruteforce(s1, t1));
    }
}

二、字符串哈希解决匹配问题

 扔掉匹配问题不看,看字符串转哈希思想的一个应用。

1147. 段式回文 - 力扣(LeetCode)

你会得到一个字符串 text 。你应该把它分成 k 个子字符串 (subtext1, subtext2,…, subtextk) ,要求满足:

  • subtexti 是 非空 字符串
  • 所有子字符串的连接等于 text ( 即subtext1 + subtext2 + ... + subtextk == text )
  • 对于所有 i 的有效值( 即 1 <= i <= k ) ,subtexti == subtextk - i + 1 均成立

返回k可能最大值。

 

示例 1:

输入:text = "ghiabcdefhelloadamhelloabcdefghi"
输出:7
解释:我们可以把字符串拆分成 "(ghi)(abcdef)(hello)(adam)(hello)(abcdef)(ghi)"。

示例 2:

输入:text = "merchant"
输出:1
解释:我们可以把字符串拆分成 "(merchant)"。

示例 3:

输入:text = "antaprezatepzapreanta"
输出:11
解释:我们可以把字符串拆分成 "(a)(nt)(a)(pre)(za)(tep)(za)(pre)(a)(nt)(a)"。

提示:

  • 1 <= text.length <= 1000
  • text 仅由小写英文字符组成

根据题目,我们要尽可能多的把字符串划分成几段,第一段和最后一段字符串相等,第二段和倒数第二段字符串相等,如果分成奇数个那么最中间的一段不需要和任何段相等。

不使用哈希的递归版本

//不使用哈希的递归版本 O(N^2)
public class Solution {
    public int longestDecomposition(String text){
        return solve(text, 0, text.length() - 1);
    }
    //s[left, right]
    //left从左往右走 right从右往左走
    private int solve(String s, int left, int right){
        if(left > right) return 0;
        for(int i = left, j = right; i < j; i++, j--){
            //s[left, i] == s[j, right]
            if(equal(s, left, i, j, right))
                return 2 + solve(s, i + 1, j - 1);
        }
        return 1;
    }
    //s[l1, r1] == s[l2, r2] ?
    private boolean equal(String s, int l1, int r1, int l2, int r2){
        for(int i = l1, j = l2; i <= r1 && j <= r2; i++, j++)
            if(s.charAt(i) != s.charAt(j)) return false;
            return true; 
    }
}

使用哈希的版本

基于哈希的思路代码整体框架和上一个不使用哈希的递归版本是一样的,区别在于给两个字符串判等的时候我们比较的是两个子串对应的哈希值,对于这两个哈希值我们不是每一次都计算一遍,不然整体还会是一个O(N^2)级别的算法。我们做的是要根据前一次计算的哈希值只通过一次计算来推导出当我们拿到新的左边的第i个字符和右边的第j个字符之后,这个新的哈希值是谁。即下图的方式。

//使用哈希 O(N)
public class Solution {

    private long MOD = (long)(1e9 + 7);//即十亿零七
    private long[] pow26;

    public int longestDecomposition(String text){
        //预处理操作,提前把26的各个次方数值存进去,用到哪个就直接提哪个
        //pow26[i] = 26^i
        //虽然这样做多用了空间,但在算法里时间比空间值钱,我们愿意用时间换空间
        pow26 = new long[text.length()];
        pow26[0] = 1;
        for(int i = 1; i < text.length(); i++){
            //求余是为了防止整型溢出
            pow26[i] = pow26[i - 1] * 26 % MOD;
        }
        return solve(text, 0, text.length() - 1);
    }

    //s[left, right]
    //left从左往右走 right从右往左走
    private int solve(String s, int left, int right){
        if(left > right) return 0;

        long prehash = 0, posthash = 0;
        for(int i = left, j = right; i < j; i++, j--){
            //(s.charAt(i) - 'a')代表a对应0,b对应1,c对应2....
            prehash = (prehash * 26 + (s.charAt(i) - 'a')) % MOD;
            posthash = ((s.charAt(j) - 'a') * pow26[right - j] + posthash) % MOD;
            //s[left, i] == s[j, right]
            if(prehash == posthash && equal(s, left, i, j, right))
                return 2 + solve(s, i + 1, j - 1);
        }
        return 1;
    }

    //s[l1, r1] == s[l2, r2] ?
    private boolean equal(String s, int l1, int r1, int l2, int r2){
        for(int i = l1, j = l2; i <= r1 && j <= r2; i++, j++)
            if(s.charAt(i) != s.charAt(j)) return false;
        return true;
    }
}

在提交到leetcode后我们发现哈希的解法却比递归的慢,因为leetcode的测试样例的数据量不够大,反而显得哈希方法比较慢,如果数据量够大,哈希法的性能就能体现出来了。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1293635.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

echarts图之 底部滚动横轴 缩放图形大小

//折线图-堆叠面积图function pileLineChart(odata, dom){//放大缩小的代码startvar dataZoom [],y240;if(odata.xData.length > 7){dataZoom [{show: true,realtime: true,startValue:0, endValue:5,left:"center",top:"auto",right:"auto"…

探索人工智能领域——每日20个名词详解【day11】

目录 前言 正文 总结 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&#xff0c;希望我的博客能对你有所帮助。 &#x1f4a1;本文由Filotimo__✍️原创&#xff0c;首发于CSDN&#x1f4da;。 &#x1f4e3;如需转载&#xff0c;请事先与我联系以…

Python Nuitka打包指南

更多Python学习内容&#xff1a;ipengtao.com 大家好&#xff0c;我是彭涛&#xff0c;今天为大家分享 Python Nuitka打包指南&#xff0c;全文2100字&#xff0c;阅读大约8分钟。 在Python应用程序开发中&#xff0c;打包是将代码和依赖项组合成可执行文件或库的关键步骤之一…

Linux操作系统下对文件的管理

文件的初步理解 C语言中我们了解过一些有关文件处理的函数&#xff0c;如&#xff1a;fopen、fclose、fread……这些函数其实都是封装了系统调用接口&#xff0c;从而利于我们直接使用。 认识文件 了解文件之前我们必须知道&#xff1a;文件内容属性。文件的属性标识着文件的…

混沌映射初始化种群与随机初始化种群初始种群分布图对比

自行切换混沌映射&#xff0c;代码如下&#xff1a; Lb -1; % 搜索空间下界 Ub 1; % 搜索空间上界N_iter 500; % 最大迭代次数 N 30; % 种群个数 dim 2; % 种群维度 Z zeros(N, dim);% 随机生成一个d维向量 Z(1, :) rand(1, dim);% 利用logistic生成N个向量 for i…

【51单片机系列】矩阵按键介绍

本节实现的功能是&#xff1a;通过开发板上的矩阵键盘控制静态数码管显示对应的键值0-F。 文章目录 一、矩阵按键介绍二、硬件设计三、软件设计 一、矩阵按键介绍 独立键盘与单片机连接时&#xff0c;每一个按键都需要单片机的一个I/O口。若某单片机系统需要较多按键&#xff…

QT----Visual Studio输入中文报错,常量中有换行符

问题描述 在VS中写qt时发现在标题中输入了中文直接把报错无法运行 解决方法1 修改文件的编码方式。在VS菜单栏 工具->自定义-》命令-》选择文件-》添加高级保存选项命令。 双加选中添加中文的文件&#xff0c;文件-》高级保存选项-》修改utf-8就可以运行了 解决方法2…

用C语言的循环嵌套打印菱形

这是用循环弄出来的&#xff0c;看的时候可以列一个表&#xff0c;将空格&#xff0c;要打印的*数&#xff0c;行数对应出来&#xff0c;因为里面涉及到一些数学公式&#xff0c;写出来的话方便观察&#xff01; #define _CRT_SECURE_NO_WARNINGS 1//C语言中用scanf可能会警告&…

【K8S】Hello World

文章目录 1 搭建本地测试环境1.1 安装 docker和 Colima1.2 安装 minikube1.3 启动minikube1.4 安装 kubectl1.5 注册 docker hub镜像仓库 2 k8s核心资源概念2.1 Pod2.2 Deployment2.3 Service2.4 Ingress 参考资料 1 搭建本地测试环境 本文以 mac os为例 1.1 安装 docker和 C…

Day53力扣打卡

打卡记录 重新规划路线&#xff08;dfs&#xff09; 链接 class Solution:def dfs(self, x: int, parent: int, e: List[List[List[int]]]) -> int:res 0for edge in e[x]:if edge[0] parent:continueres edge[1] self.dfs(edge[0], x, e)return resdef minReorder(se…

Android 11.0 MTK Camera2 设置默认拍照尺寸功能实现

1.前言 在11.0的系统rom定制化开发中,在mtk平台的camera2关于拍照的一些功能修改中,在一些平台默认需要设置最大的分辨率 来作为拍照的分辨率,所以就需要了解拍照尺寸设置流程,然后来实现相关的功能 如图: 2.MTK Camera2 设置默认拍照尺寸功能实现的核心类 \vendor\me…

Terraform实战(二)-terraform创建阿里云资源

1 初始化环境 1.1 创建初始文件夹 $ cd /data $ mkdir terraform $ mkdir aliyun terraform作为terraform的配置文件夹&#xff0c;内部的每一个.tf&#xff0c;.tfvars文件都会被加载。 1.2 配置provider 创建providers.tf文件&#xff0c;配置provider依赖。 provider…

AUTOSAR 入门

前言 AUTOSAR是什么Vector DaVinci 工具功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个注脚注释也是必…

nodejs微信小程序+python+PHP的智能停车系统-计算机毕业设计推荐django

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

Leetcode刷题笔记题解(C++):165. 比较版本号

思路&#xff1a;利用小数点来分开求和&#xff0c;判断和是否相等来推断两个版本号是否一致 class Solution { public:int compareVersion(string version1, string version2) {int i0;//记录version1的字符下标int j0;//记录version2的字符下标int num10;//保存version1的和…

【Android】查看keystore的公钥和私钥

前言&#xff1a; 查看前准备好.keystore文件&#xff0c;安装并配置openssl、keytool。文件路径中不要有中文。 一、查看keystore的公钥&#xff1a; 1.从keystore中获取MD5证书 keytool -list -v -keystore gamekeyold.keystore 2.导出公钥文件 keytool -export -alias …

在线学习平台-班级模块

在线学习平台-项目搭建 在线学习平台-需求分析 若依的基本使用 通过分析可知,班级模块的结构会比较简单,可以先从班级模块入手 1.先在domain里写上班级里的属性 快捷方式: 时区可以这里找,时区和数据库名之间要加一个 ? 右键需要的数据库模型,便可直接生成 生成的实体类不…

智能优化算法应用:基于蛇优化算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于蛇优化算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于蛇优化算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.蛇优化算法4.实验参数设定5.算法结果6.参考文献7.…

服务器配置免密SSH

在当今互联网时代&#xff0c;远程工作和网络安全已成为信息技术领域的热点话题。无论是管理远程服务器、维护网络设备还是简单地从家中连接到办公室&#xff0c;安全始终是首要考虑的因素。这就是为什么 SSH&#xff08;Secure Shell&#xff09;成为了网络专业人士的首选工具…

Python---类的综合案例

1、需求分析 设计一个Game类 属性&#xff1a; 定义一个类属性top_score记录游戏的历史最高分 定义一个实例属性player_name记录当前游戏的玩家姓名 方法&#xff1a; 静态方法show_help显示游戏帮助信息 类方法show_top_score显示历史最高分 实例方法start_game开始当前…