字符串匹配算法

Posted duanshuai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字符串匹配算法相关的知识,希望对你有一定的参考价值。

一. 简单的直接算法

比较次数:(n-m-1)*m次

时间复杂度O(mn)

二. Rabin-karp算法

  • 算法思想:将字符串转化成数字进行粗比较,筛选后进行细比较
  • 算法设计:

(1)直接数值比较

      • 算法思想:字符集与 1-n 的数值满足双射,字符串转化为n进制数值
      • 优化程度:a. 比较次数:n-m次。

                                                b. 计算次数:1 + n-m 次

      • 问题:m位数的计算复杂,优化程度低

(2)hash函数数值比较

      • 算法思想:将较大的数值用hash函数映射到较小的数
      • 优化方法(假设n=10):

 

预处理:fp = p[ m-1 ] + 10*(p[ m-2 ] + …+ 10*(p[ 1 ] + 10*p[ 0 ] ))) mod q。

移位重新计算:

 

      • 复杂度分析:当q是素数时,平均:O(n+m),最坏:O(mn)

三.BM算法

1. 算法思想:

(1)从后往前匹配的好处:在比较过程中不匹配的概率远远大于匹配的概率,基于这一特点,在匹配失败时,从后往前匹配的跳跃位置更大

(2)每次发生不匹配,根据好后缀规则和坏字符规则(规则都是对模式串而言的)跳转到下一次比较的位置

2. 算法设计

(1)预处理:(对模式串T进行预处理)P[ 0-n ]

         坏字符规则:后移位数 = 失配位置 - 模式串上一次出现坏字符的位置(未出现记为 -1)

         好后缀规则:后移位数 =  好后缀的位置 - 模式串上一次出现好后缀的位置(未出现记为 -1)

(2)从左到右移动,从后往前比较,失配时移动位置 = max{ 坏字符规则 , 好后缀规则}

四. BMH算法

1. 算法思想:

总体上是BM算法的改进,关注点在模式串的最后一个字符,规则更简单

2. 算法设计

(1)预处理(对字符集/文本串预处理)

偏移表:P[ 0-m-1 ]

技术图片

 

(2)从左到右移动,从后往前比较

五. KMP算法---最坏情况依旧是线性

1. 算法思想:

文本中的每个字符仅匹配一次,充分利用已经匹配的部分做跳转

2. 算法设计

(1)计算最长公共前后缀:maxL

关于如何计算最长公共前后缀(例如P=abaabcac):

A.暴力算法:

得到所有前缀和后缀,分别比较。

B. 递推算法:

得到P的所有前缀,第一个前缀的maxL初始化为0。

假设已经求得第 i 个前缀的maxLi = k , 求解第 i + 1 个前缀的maxL(i+1)

若 P[ k ] == P[ i ],maxL(i+1)= k+1;

否则,使用暴力算法计算maxL.

例:

a  0

ab  0  递推

aba   1  递推

abaa   1  递推

abaab   2  递推(举例1)

abaabc   0  暴力(举例2)

abaabca   1  递推

abaabcac   0  暴力

 

maxL = { 0、0、1、1、2、0、1、0}

(举例1)第四前缀abaa:maxL = 1,又P[ 1 ]==P[ 4 ] == b,则第五前缀abaab:maxL = 2

(举例2)此时不满足P[ k ] == P[ i ],暴力求解,

得到abaabc的所有前缀和所有后缀,对应比较

abaabcabaabc

a                   c  0

ab                bc  0

aba            abc  0

abaa        aabc  0

abaab    baabc  0

则第六前缀abaabc:maxL = 0

 

 

 

(2).将maxlL整体右移一位,初始为 -1,得到next数组

next = { -1、0、0、1、1、2、0、1}

(3)从左到右,从前往后匹配,失配时,将 next数组对应的值作为下标与失配位置对齐(j = next[ j ])

 

 

 

         

 

以上是关于字符串匹配算法的主要内容,如果未能解决你的问题,请参考以下文章

字符串匹配算法的使用(未完待整理)

kmp匹配

字符串的模式匹配算法

Java编程实现字符串的模式匹配

数据结构与算法——字符串匹配问题(KMP算法)

求一个基于java的模糊匹配算法