云漫圈 | 什么是字符串匹配算法?

作者 | 程序员小灰

来源 | 程序员小灰(ID:chengxuyuanxiaohui )

—————  第二天  —————


什么意思呢?让我们来举一个例子:

在上图中,字符串B是A的子串,

B第一次在A中出现的位置下标是2(字符串的首位下标是0),

所以返回 2。

我们再看另一个例子:

在上图中,字符串B在A中并不存在,

所以返回 -1。

为了统一概念,

在后文中,

我们把字符串A称为主串,

把字符串B称为模式串。

小灰的想法简单粗暴,

让我们用下面的例子来演示一下:

第一轮,我们从主串的首位开始,

把主串和模式串的字符逐个比较:

显然,主串的首位字符是a,

模式串的首位字符是b,两者并不匹配。

第二轮,我们把模式串后移一位,

从主串的第二位开始,

把主串和模式串的字符逐个比较:

主串的第二位字符是b,

模式串的第二位字符也是b,

两者匹配,继续比较:

主串的第三位字符是b,

模式串的第三位字符也是c,

两者并不匹配。

第三轮,我们把模式串再次后移一位,

从主串的第三位开始,

把主串和模式串的字符逐个比较:

主串的第三位字符是b,

模式串的第三位字符也是b,

两者匹配,继续比较:

主串的第四位字符是c,

模式串的第四位字符也是c,

两者匹配,继续比较:

主串的第五位字符是e,

模式串的第五位字符也是e,

两者匹配,比较完成!

由此得到结果,

模式串 bce 是主串 abbcefgh 的子串,

在主串第一次出现的位置下标是 2:

以上就是小灰想出的解决方案,

这个算法有一个名字,叫做BF算法,

是Brute Force(暴力算法)的缩写。

上图的情况,在每一轮进行字符匹配时,

模式串的前三个字符a都和主串中的字符相匹配,

一直检查到模式串最后一个字符b,才发现不匹配:

这样一来,

两个字符串在每一轮都需要白白比较4次,

显然非常浪费。

假设主串的长度是m,

模式串的长度是n,

那么在这种极端情况下,

BF算法的最坏时间复杂度是O(mn)。

————————————

比较哈希值是什么意思呢?

用过哈希表的朋友们都知道,

每一个字符串都可以通过某种哈希算法,

转换成一个整型数,

这个整型数就是hashcode:

hashcode = hash(string)

显然,相对于逐个字符比较两个字符串,

仅比较两个字符串的hashcode要容易得多。

给定主串和模式串如下

(假定字符串只包含26个小写字母):

第一步,

我们需要生成模式串的hashcode。

生成hashcode的算法多种多样,比如:

按位相加

这是最简单的方法,

我们可以把a当做1,b当做2,c当做3......

然后把字符串的所有字符相加,

相加结果就是它的hashcode。

bce =  2 + 3 + 5 = 10

但是,这个算法虽然简单,

却很可能产生hash冲突,

比如bce、bec、cbe的hashcode是一样的。

转换成26进制数

既然字符串只包含26个小写字母,

那么我们可以把每一个字符串当成一个26进制数来计算。

bce = 2*(26^2) + 3*26 + 5 = 1435

这样做的好处是大幅减少了hash冲突,

缺点是计算量较大,

而且有可能出现超出整型范围的情况,

需要对计算结果进行取模。

为了方便演示,

后续我们采用的是按位相加的hash算法,

所以bce的hashcode是10:

第二步,

生成主串当中第一个等长子串的hashcode。

由于主串通常要长于模式串,

把整个主串转化成hashcode是没有意义的,

只有比较主串当中和模式串等长的子串才有意义。

因此,

我们首先生成主串中第一个和模式串等长的子串hashcode,

即abb = 1 + 2 + 2 = 5:

第三步,比较两个hashcode。

显然,5!=10,

说明模式串和第一个子串不匹配,

我们继续下一轮比较。

第四步,

生成主串当中第二个等长子串的hashcode。

bbc = 2 + 2 + 3 = 7:

第五步,比较两个hashcode。

显然,7!=10,说明模式串和第二个子串不匹配,

我们继续下一轮比较。

第六步,生成主串当中第三个等长子串的hashcode。

bce= 2 + 3 + 5 = 10:

第七步,比较两个hashcode。

显然,10 ==10,两个hash值相等!

这是否说明两个字符串也相等呢?

别高兴的太早,

由于存在hash冲突的可能,

我们还需要进一步验证。

第八步,逐个字符比较两字符串。

hashcode的比较只是初步验证,

之后我们还需要像BF算法那样,

对两个字符串逐个字符比较,

最终判断出两个字符串匹配。

最后得出结论,

模式串bce是主串abbcefgh的子串,

第一次出现的下标是2。

什么意思呢?让我们再来看一个例子:


上图中,

我已知子串abbcefg的hashcode是26,

那么如何计算下一个子串,

也就是bbcefgd的hashcode呢?

我们没有必要把子串的字符重新进行累加运算,

而是可以采用一个更简单的方法。

由于新子串的前面少了一个a,

后面多了一个d,所以:

新hashcode = 旧hashcode - 1 + 4 = 26-1+4 = 29 

再下一个子串bcefgde的计算也是同理:

新hashcode = 旧hashcode - 2 + 5 = 29-2+5 = 32

 

public static int rabinKarp(String str, String pattern){
//主串长度
int m = str.length();
//模式串的长度
int n = pattern.length();
//计算模式串的hash值
int patternCode = hash(pattern);
//计算主串当中第一个和模式串等长的子串hash值
int strCode = hash(str.substring(0, n));//用模式串的hash值和主串的局部hash值比较。
//如果匹配,则进行精确比较;如果不匹配,计算主串中相邻子串的hash值。
for (int i=0; i<m-n+1; i++) {
if(strCode == patternCode && compareString(i, str, pattern)){
return i;
}
//如果不是最后一轮,更新主串从i到i+n的hash值
if(i<m-n){
strCode = nextHash(str, strCode, i, n);
}
}return -1;
}private static int hash(String str){
int hashcode = 0;
//这里采用最简单的hashcode计算方式:
//把a当做1,把b当中2,把c当中3.....然后按位相加
for (int i = 0; i < str.length(); i++) {
hashcode += str.charAt(i)-'a';
}
return hashcode;
}private static int nextHash(String str, int hash, int index, int n){
hash -= str.charAt(index)-'a';
hash += str.charAt(index+n)-'a';
return hash;
}private static boolean compareString(int i, String str, String pattern) {
String strSub = str.substring(i, i+pattern.length());
return strSub.equals(pattern);
}public static void main(String[] args) {
String str = "aacdesadsdfer";
String pattern = "adsd";
System.out.println("第一次出现的位置:" + rabinKarp(str, pattern));
}

为了助力对抗疫情,减少线下人员流动和聚集,CSDN与 PyCon 官方授权的 PyCon中国社区合作,举行「Python开发者日」在线系列峰会。通过精彩的技术干货内容、有趣多元化的在线互动活动等,让您足不出户便可与大咖学习交流,共同渡过抗疫攻坚期。

活动咨询,可扫描下方二维码加入官方交流群⬇️⬇️⬇️

福利

扫描添加小编微信,备注“姓名+公司职位”,入驻【CSDN博客】,加入【云计算学习交流群】,和志同道合的朋友们共同打卡学习!

推荐阅读:

  • 大数据抗疫的“洪荒之力”:多地政府借力大数据技术,多家企业上马大数据产品

  • “云原生全家桶“KubeSphere 如何让企业从容迈进云原生时代?

  • 为什么说程序员做外包没前途?

  • 官宣了!受疫情影响,程序员可免费领这些!

  • 12 大 AI App 技术创意,教你如何在 2020 年赚到钱!

  • 远程办公绝非远程监控,该如何挖掘远程办公的红利?

真香,朕在看了!

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

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

相关文章

MSSQL实践-数据库备份加密

摘要 在SQL Server安全系列专题月报分享中&#xff0c;我们已经分享了&#xff1a;如何使用对称密钥实现SQL Server列加密技术、使用非对称密钥实现SQL Server列加密、使用混合密钥实现SQL Server列加密技术、列加密技术带来的查询性能问题以及相应解决方案、行级别安全解决方…

Kubernetes 如何打赢容器之战?

Kubernetes 近几年很热门&#xff0c;在各大技术论坛上被炒的很火。它提供了强大的容器编排能力&#xff0c;与此同时 DevOps 的概念也来到大家身边&#xff0c;广大的开发同学也能简单地运维复杂的商业化分布式系统&#xff0c;打破了传统开发和运维之间的界限。 本文会以初学…

一行Python代码能干什么?有意思!

我下班最大的乐趣就是刷抖音一开始刷的都是一些无聊小剧场后来看看能不能刷一些技术上的内容因为本人觉得Java是世界上最好的编程语言可是我在刷抖音的时候刷到了一行Python代码能干什么我突然觉得爱上Python了之前是听说Python比较简单同样的内容Java、C语言需要十几行Python只…

自然语言生成(NLG)的好处是什么,它如何影响BI?

近年来&#xff0c;我们已经看到了大数据的成功应用&#xff0c;但根据研究&#xff0c;只有20&#xff05;的员工能够真正的使用BI工具。此外&#xff0c;由于在统计思维方面缺乏培训且图表和图表形式的数据不是很清晰&#xff0c;决策者往往会出现误解和决策失误。而这背后的…

ida 字符串查找_IDA 搜索中文字符串

IDA 的字符串窗口默认只能显示英文&#xff0c;网上的一些方法是指定启动时的参数可以显示中文ida64 -DCULTUREallida -DCULTUREall还有就是修改 cfg/ida.cfg 文件&#xff0c;但是这两种方法都没试成功。实际上没有那么麻烦&#xff0c;IDA 7.0 操作很方便&#xff0c;在字符串…

“练好内功坚持被集成”,阿里云发布SaaS加速器

在3月21日的2019阿里云峰会北京上&#xff0c;阿里云发布新产品SaaS加速器&#xff1a;人工智能、虚拟现实等技术能力被集成为模块&#xff0c;ISV和开发者只要简单拖拽&#xff0c;就可以快速搭建SaaS应用。 发布现场&#xff0c;阿里云智能产品管理部总经理马劲进行简单演示…

2020 年,云游戏将爆发?各大科技公司云游戏布局大曝光!

作者 | 年素清责编 | 伍杏玲出品 | CSDN云计算&#xff08;ID&#xff1a;CSDNcloud&#xff09; 伴随5G技术加速落地&#xff0c;云游戏作为5G应用落地的最佳场景&#xff0c;已经成为全球游戏厂商和云服务厂商布局的重要战场。根据艾媒咨询数据显示&#xff0c;2018年中国云游…

Springboot整合Quartz集群部署以及配置Druid数据源

参考链接&#xff1a; https://blog.csdn.net/wangmx1993328/article/details/105441308 https://blog.csdn.net/qq_39669058/article/details/90411497 参数配置连接&#xff1a;https://github.com/wangmaoxiong/quartzjdbc/blob/master/src/main/resources/application-clu…

我是如何拿到蚂蚁金服实习 offer 的

我是2018年3月入职蚂蚁的应届前端工程师&#xff0c;来自于北京邮电大学。2年前的此刻&#xff0c;我也是实习求职大潮中的一员&#xff0c;在这里&#xff0c;分享一下我从准备面试到实习&#xff0c;再到最终正式入职的经历。 选择蚂蚁 阿里的前端水平在业界有着很高的评价…

java 客户化排序_第八部分_客户化JSP标签

EL语言(减少JSP页面中的Java代码)String password request.getParameter("password");%>username: password: username: ${param.username }password: ${param.password }属性范围->在EL中的名称Page->pageScope&#xff1b;Request->requestScope&…

十大类疫情服务紧缺 阿里广发英雄帖抗疫小程序开发者最高可获50万元奖励

全民积极响应国家抗击新冠肺炎疫情的号召&#xff0c;正催生出越来越多新的互联网服务缺口。基于对用户、政府、企事业单位抗疫服务需求的紧缺情况调查&#xff0c;支付宝今日面向社会各界开发者发布“10大疫情期最急需服务开发清单”&#xff0c;号召更多开发者投入进来开发更…

信用算力基于 RocketMQ 实现金融级数据服务的实践

微服务架构已成为了互联网的热门话题之一&#xff0c;而这也是互联网技术发展的必然阶段。然而&#xff0c;微服务概念的提出者 Martin Fowler 却强调&#xff1a;分布式调用的第一原则就是不要分布式。 纵观微服务实施过程中的弊端&#xff0c;可以推断出作者的意图&#xff…

六年打磨!阿里开源混沌工程工具 ChaosBlade

阿里妹导读&#xff1a;减少故障的最好方法就是让故障经常性的发生。通过不断重复失败过程&#xff0c;持续提升系统的容错和弹性能力。今天&#xff0c;阿里巴巴把六年来在故障演练领域的创意和实践汇浓缩而成的工具进行开源&#xff0c;它就是 “ChaosBlade”。如果你想要提升…

jmeter-5.3 测试http接口动态数据 windows+Linux双环境

文章目录一、基础组件1. 企业需求2. 创建线程组&#xff1a;3. 创建HTTP请求4. CSV 数据文件组件5. 响应断言二、添加监听器2.1. 添加察看结果树2.2. 添加聚合报告2.3. 监听每秒事务数2.4. 监听 随时间变化的响应时间三、HTTP请求配置3.1. 基础参数四、 响应断言配置四、 CSV 数…

阿里达摩院又火了!引入AI确诊肺炎提速16倍,仅需半小时!网友神回复了

针对新型冠状病毒的确诊&#xff0c;全国大多数医院基本都采用核酸检测。果壳网发文称&#xff1a;从病人样本送到实验室即刻开始测试&#xff0c;到出检测报告&#xff0c;差不多需要8个小时。但是8个小时太长&#xff0c;在现在这种病毒传播速度下&#xff0c;让人焦急万分。…

用java写ods系统_基于数据库的代码自动生成工具,生成JavaBean、生成数据库文档、生成前后端代码等(TableGo v7.0.0版)...

TableGo是基于数据库的代码自动生成工具&#xff0c;低代码编程技术的实现&#xff0c;可以零代码自动生成SpringBoot项目工程、生成JavaBean、生成前后端分离的CRUD代码、生成MyBaits的Mapper映射配置文件、生成数据库设计文档(Word、Excel)、生成Swagger2离线API文档、生成前…

Node.js 应用故障排查手册 —— 冗余配置传递引发的内存溢出

楔子 前面一小节我们以一个真实的压测案例来给大家讲解如何利用 Node.js 性能平台 生成的 CPU Profile 分析来进行压测时的性能调优。那么与 CPU 相关的问题相比&#xff0c;Node.js 应用中由于不当使用产生的内存问题是一个重灾区&#xff0c;而且这些问题往往都是出现在生产…

一分钟在Linux 环境 搭建 SFTP服务器

文章目录一、实战1. 创建sftp组&#xff1a;2. 创建一个用户sftpuser&#xff1a;3. 设置sftpuser用户的密码&#xff0c;会要求你输入两次密码确认&#xff1a;4. 创建一个sftp的上传目录&#xff1a;5. 修改用户sftpuser所在的目录&#xff1a;6. 配置sshd_config&#xff1a…

微服务架构何去何从?

戳蓝字“CSDN云计算”关注我们哦&#xff01;作者 | 孙玄本文经授权转载自架构之美前言微服务架构模式经过5年多的发展&#xff0c;在各行各业如火如荼地应用和实践。如何在企业中优雅地设计微服务架构&#xff1f;是企业面对的一个重要问题。本文将讲述微服务架构1.0设计与实践…

天马行空脚踏实地,阿里巴巴有群百里挑一的天才应届生

阿里巴巴有一群天马行空脚踏实地的阿里星。 天下网商记者 王安忆 阿里巴巴的春季校招已经启动。在阿里的技术大咖储备团队中&#xff0c;有三分之一是来自高校招聘&#xff0c;这当中&#xff0c;有一项名为阿里星的神秘计划。这是校招中专门针对高校顶尖大学生的一个培养计划&…