专业IT网络知识平台,分享IT百科知识、生活百科知识解答!

易企推科技
易企推科技

匹配算法有哪些,常用的字符串匹配算法最全详解

来源:小易整编  作者:小易  发布时间:2023-02-08 09:19
摘要:匹配算法有哪些,常用的字符串匹配算法最全详解子字符串匹配子字符串匹配算法的定义:文本长度:N模式字符串长度:M有效位移:s解决字符串的匹配算法有非常多,目前常用的有以下几种:暴力查找KMP算法Boyer-Moore算法Rabin-Karp指...

匹配算法有哪些,常用的字符串匹配算法最全详解

匹配算法有哪些,常用的字符串匹配算法最全详解

匹配算法有哪些,常用的字符串匹配算法最全详解

根据"坏字符规则",此时搜索词应该后移 2 - (-1)= 3 位。问题是,此时有没有更好的移法?

比较前面一位,"MPLE"与"MPLE"匹配。我们把这种情况称为"好后缀"(good suffix),即所有尾部匹配的字符串。注意,"MPLE"、"PLE"、"LE"、"E"都是好后缀

"好后缀规则":后移位数 = 好后缀的位置 - 搜索词中的上一次出现位置

这个规则有三个注意点:

(1)"好后缀"的位置以最后一个字符为准。假定"ABCDEF"的"EF"是好后缀,则它的位置以"F"为准,即5(从0开始计算)。

(2)如果"好后缀"在搜索词中只出现一次,则它的上一次出现位置为 -1。比如,"EF"在"ABCDEF"之中只出现一次,则它的上一次出现位置为-1(即未出现)。

(3)如果"好后缀"有多个,则除了最长的那个"好后缀",其他"好后缀"的上一次出现位置必须在头部。比如,假定"BABCDAB"的"好后缀"是"DAB"、"AB"、"B",请问这时"好后缀"的上一次出现位置是什么?回答是,此时采用的好后缀是"B",它的上一次出现位置是头部,即第0位。这个规则也可以这样表达:如果最长的那个"好后缀"只出现一次,则可以把搜索词改写成如下形式进行位置计算"(DA)BABCDAB",即虚拟加入最前面的"DA"。

回到上文的这个例子。此时,所有的"好后缀"(MPLE、PLE、LE、E)之中,只有"E"在"EXAMPLE"还出现在头部,所以后移 6 - 0 = 6位。

可以看到,"坏字符规则"只能移3位,"好后缀规则"可以移6位。所以,Boyer-Moore算法的基本思想是,每次后移这两个规则之中的较大值。

Boyer–Moore 算法的精妙之处在于,其通过两种启示规则来计算后移位数,且其计算过程只与模式 P 有关,而与文本 T 无关。因此,在对模式 P 进行预处理时,可预先生成 "坏字符规则之向后位移表" 和 "好后缀规则之向后位移表",在具体匹配时仅需查表比较两者中最大的位移即可。

Rabin-Karp

首先计算模式字符串的散列函数, 如果找到一个和模式字符串散列值相同的子字符串, 那么继续验证两者是否匹配.

这个过程等价于将模式保存在一个散列表中, 然后在文本中的所有子字符串查找. 但不需要为散列表预留任何空间, 因为它只有一个元素.

基本思想

长度为M的字符串对应着一个R进制的M位数, 为了用一张大小为Q的散列表来保存这种类型的键, 需要一个能够将R进制的M位数转化为一个0到Q-1之间的int值散列函数, 这里可以用除留取余法.

举个例子, 需要在文本 3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 查找模式 2 6 5 3 5, 这里R=10, 取Q=997, 则散列值为

2 6 5 3 6 % 997 = 613

然后计算文本中所有长度为5的子字符串并寻找匹配

3 1 4 1 5 % 997 = 5081 4 1 5 9 % 997 = 201......2 6 5 3 6 % 997 = 613 (匹配)

计算散列函数

在实际中,对于5位的数值, 只需要使用int就可以完成所有需要的计算, 但是当模式长度太大时, 我们使用Horner方法计算模式字符串的散列值

2 % 997 = 2

2 6 % 997 = (2*10 + 6) % 997 = 26

2 6 5 % 997 = (26*10 + 5) % 997 = 265

2 6 5 3 % 997 = (265*10 + 3) % 997 = 659

2 6 5 3 5 % 997 = (659*10 + 5) % 997 = 613

这里关键的一点就是在于不需要保存这些数的值, 只需保存它们除以Q之后的余数.

取余操作的一个基本性质是如果每次算术操作之后都将结果除以Q并取余, 这等价于在完成所有算术操作之后再将最后的结果除以Q并取余.

算法实现:

构造函数为模式字符串计算了散列值patHash并在变量中保存了R^(M-1) mod Q的值, hashSearch()计算了文本前M个字母的散列值并和模式字符串的散列值比较, 如果没有匹配, 文本指针继续下移一位, 计算新的散列值再次比较,知道成功或结束.

Java代码:

蒙特卡洛算法和拉斯维加斯算法区别:

匹配算法有哪些,常用的字符串匹配算法最全详解

总结

优点:

  • 暴力查找算法:实现简单且在一般情况下工作良好(Java的String类型的indexOf()方法就是采用暴力子字符串查找算法);

  • Knuth-Morris-Pratt算法能够保证线性级别的性能且不需要在正文中回退;

  • Boyer-Moore算法的性能一般情况下都是亚线性级别;

  • Rabin-Karp算法是线性级别;

缺点:

  • 暴力查找算法所需时间可能和NM成正比;

  • Knuth-Morris-Pratt算法和Boyer-Moore算法需要额外的内存空间;

  • Rabin-Karp算法内循环很长(若干次算术运算,其他算法都只需要比较字符);

匹配算法有哪些,常用的字符串匹配算法最全详解

匹配算法有哪些,常用的字符串匹配算法最全详解


本文地址:IT问答频道 https://www.hkm168.com/itwenda/903057_2.html,易企推百科一个免费的知识分享平台,本站部分文章来网络分享,本着互联网分享的精神,如有涉及到您的权益,请联系我们删除,谢谢!

共2页 1 2 当前是最后一页

IT问答
小编:小易整编
相关文章相关阅读
  • php怎么实现对字符串的排序

    php怎么实现对字符串的排序

    实现步骤:1、利用str_split()函数将字符串转为字符数组,语法“str_split(字符串)”;2、使用asort()或arsort()函数来对字符数组进行升序排序或降序排序,语法“asort(字符数组)”或“arsort(字符数组...

  • 如何使用PHP中的字符串变量

    如何使用PHP中的字符串变量

    如何使用PHP中的字符串变量在PHP中,字符串变量是一种非常常见的数据类型,用于存储和操作文本数据。在本文中,我们将介绍如何使用PHP中的字符串变量,并提供一些具体的代码示例。字符串变量的声明和赋值在PHP中,要声明一个字符串变量,只需要使...

  • 二进制算法怎么算

    二进制算法怎么算

    二进制算法是一种基于二进制数的运算方法,其基本运算包括加法、减法、乘法和除法。除了基本运算外,二进制算法还包括逻辑运算、位移运算等操作。逻辑运算包括与、或、非等操作,位移运算包括左移和右移操作。这些操作都有对应的规则和操作数的要求。二进制算...

  • DTW算法是什么

    DTW算法是什么

    dtw算法是指动态时间规整算法,是基于动态规划dp的思想,是一种计算2个时间序列尤其是不同长度序列相似度的一种动态规划算法;它解决了发音长短不一的模板匹配问题,是语音识别中出现较早、较为经典的一种算法。dtw算法主要应用在时序数据上,比如孤...

  • javascript如何将数组转换为字符串

    javascript如何将数组转换为字符串

    javascript将数组转换为字符串的方法:1、使用join()函数,将数组元素用分隔符连接起来以构建一个字符串,语法格式“arr.join("分隔符")”;2、使用tostring()函数,语法格式“string(a......

  • php怎么将一个字符串转成数组(三种方法)

    php怎么将一个字符串转成数组(三种方法)

    在php中,有时候我们需要将一个字符串转换成数组,以方便对其进行操作和处理。以下是一些简单的方法来实现这个目标。方法一:使用explode()函数explode()函数可以将一个字符串分割成数组。它需要两个参数:一个分割符和一个字符串。分割...

  • javascript如何获取字符串长度

    javascript如何获取字符串长度

    javascript获取字符串长度的方法:1、使用length属性按字符来获取字符串长度,语法“字符串.length”;2、利用charcodeat()按字节来获取字符串长度。本教程操作环境:windows7系统、javascript1.8...

  • 字符串如何比较大小

    字符串如何比较大小

    字符串比较大小的步骤:1、将要比较的两个字符串分别赋给两个变量;2、比较两个字符串的长度,较短的字符串将被认为是较小的字符串;3、如果长度相同,逐个比较它们的字符;4、从字符串的第一个字符开始,比较两个字符串的ascii值;5、如果asci...

  • 周排行
  • 月排行
  • 年排行

精彩推荐