📜  z 函数 (1)

📅  最后修改于: 2023-12-03 15:21:22.867000             🧑  作者: Mango

Z函数

Z函数是一种字符串匹配算法,用于在一个文本串中寻找一个子串的出现位置。Z函数的时间复杂度为O(n),其中n为文本串的长度。Z函数是由Gusfield在1997年提出的。

算法原理

Z函数的核心思想是维护一个覆盖最右侧位置的最长字符串。假设p为当前最右侧的字符串结束位置,l为此字符串的起始位置,r为此字符串的结束位置,则有以下两种情况:

  1. 如果i > p,则暴力匹配s[i]和s[0],找到l和r,同时将p更新为r。
  2. 如果i ≤ p,则首先计算当前字符在此字符串中的位置k(k = i - l),如果z[k] < p - i + 1,则说明s[i:k + 1]和s[l:r + 1]不等;否则,由于s[i:k + 1]与s[0:k - i + 1]相等,而前半部分s[0:k - i + 1]的Z值为z[k],因此,要么z[i] = z[k],要么z[i] ≥ p - i + 1。
算法流程

在使用Z函数进行字符串匹配时,需要先将模式串和文本串合并,并在其中插入一个分隔符,以避免越界。具体流程如下:

  1. 将模式串和文本串合并,并在中间插入一个分隔符,时间复杂度为O(n)。
  2. 初始化一个长度为n的数组Z,其中Z[0]赋值为0。
  3. 初始化最右侧的字符串结束位置p = 0,字符串起始位置l = 0。
  4. 从i = 1开始遍历合并串,对于每个i,判断其是否大于p,如果是,就暴力匹配s[i]和s[0],找到l和r,并将p更新为r;否则,计算当前字符在此字符串中的位置k,然后按照上述原理进行更新Z[i]的值。
  5. 遍历Z数组,找到所有值为模式串长度的位置,即为匹配成功的位置。
示例代码

下面是Python的实现代码,其中模式串和文本串已经合并并在其中间插入了一个分隔符"|"。返回的是一个列表,包含所有匹配成功的位置。请注意,此代码并未对文本串、模式串、以及返回结果进行任何错误处理,请使用时自行处理。


def z_algorithm(s):
    n = len(s)
    Z = [0] * n
    Z[0] = n
    p = 0
    l = 0
    for i in range(1, n):
        if i > p:
            k = 0
            while i + k < n and s[k] == s[i + k]:
                k += 1
            if k == 0:
                Z[i] = 0
            else:
                Z[i] = k
                p = i + k - 1
                l = i
        else:
            k = i - l
            if Z[k] < p - i + 1:
                Z[i] = Z[k]
            else:
                j = p + 1
                while j < n and s[j - i] == s[j]:
                    j += 1
                Z[i] = j - i
                p = j - 1
                l = i
    return [i - n for i in range(n) if Z[i] == n - i]