字符串的模式匹配算法(思想+python实现)

朴素的模式匹配算法

一个例子:

从主串 S = "goodjob"中,找到子串 T = "job"的位置。我们通常需要下面的步骤。

1. 将子串"job"与主串S从第一位对应匹配。即判断 whether 'g' == 'j';
2. 判断结果为否,继续匹配 whether 'o' == 'j';
3. 直到找到第一位匹配 'j' = 'j';
4. 继续匹配完整 S[4:7] == 'job' == T。

是一种最简单的匹配算法,暴力易实现,但有许多冗余的步骤。

KMP 模式匹配算法

总的思想是:通过字符串已有的信息来规避朴素模式匹配中可以省略的步骤。

详细的过程不再赘述,在这里只进行简要的说明。

已知主串的下标为 i i i, 子串的下标为 j j j, 总结下来是两短句:“ i i i 不回溯, j j j n e x t next next”。

i i i 不回溯:指的是在匹配过程中,主串的匹配下标永远只会增加或不变,不会再去匹配之前主串的下标。

j j j n e x t next next:指的是子串的下标匹配规则是依照 n e x t next next 数组值。

那么下面要详细说明 n e x t next next 数组值是什么。

n e x t next next 数组值推导

先给出数学式的定义:
n e x t [ j ] = { 0 , 当 j = 1时 M a x { k ∣ 1 < k < j , 且 ′ p 1 . . . p k − 1 ′ = ′ p j − k + 1 . . . p j − 1 ′ } 当 此 集 合 不 空 时 1 , 其他情况 next[j] = \begin{cases} 0, & \text{当 j = 1时} \\[2ex] Max\{ k | 1<k<j,且'p_1 ...p_{k-1}' ='p_{j-k+1}...p_{j-1}'\}& \text当此集合不空时\\[2ex] 1, & \text{其他情况} \end{cases} next[j]=0,Max{ k1<k<jp1...pk1=pjk+1...pj1}1 j = 1其他情况
e.g. T = “abcabx”
j 123456 模 式 串 T a b c a b x n e x t [ j ] 011123 \begin{array}{c|lcr} j & 123456 \\ \hline 模式串T & abcabx \\ next[j] & 011123 \end{array} jTnext[j]123456abcabx011123
其中的一个子串"abcab", abcab,前缀和后缀有两个字符相等,则 n e x t [ 6 ] = 2 + 1 = 3 next[6] = 2 + 1 = 3 next[6]=2+1=3

整个算法的时间复杂度时 O(n + m),相较于朴素模式匹配算法的 O((n - m + 1) * m)来说,较好一些(T的长度为m)。

KMP模式匹配算法改进

一个例子:主串S = “aaaabcde”,子串T = “aaaaax”,其 next 数组值分别为 012345,在开始时,当 i = 5, j = 5时,我们发现"b" 与 "a"不想等,因此,j = next[5] = 4,此时 "b"与第四位置的"a"依然不等,j = next[4] = 3 … 这样也会多出很多冗余的步骤。所以,我们对求解next函数进行了改进。

在每次赋值next的时候增加一个判断,判断 w h e t h e r   T [ i ] = = T [ j ] whether\ T[i] == T[j] whether T[i]==T[j]

最后给出具体的python求解next数组的程序:

import numpy as np

def get_nextval(T):
    T = '#' + T
    i = 1
    j = 0
    nextval = np.zeros(len(T), dtype=int)
    
    while i < len(T)-1:
        if j == 0 or T[i] == T[j]:
            i = i + 1
            j = j + 1
            if T[i] != T[j]:
                nextval[i] = j
            else:
                nextval[i] = nextval[j]
        else: 
            j = nextval[j]
    nextval = np.delete(nextval,0)
    return nextval

− − − − − − − − − − − − − − − − ----------------
该文章首发于 zyairelu.cn
欢迎来到我的网站进行评论及研讨
个人邮箱[email protected]
− − − − − − − − − − − − − − − − ----------------

猜你喜欢

转载自blog.csdn.net/weixin_42731543/article/details/103587078