Z 函数与后缀数组入门:从前缀匹配到全局子串关系

理解 Z 函数如何描述后缀与前缀匹配,后缀数组如何排序所有后缀并处理重复子串和 LCP。

已发布文章计算机基础入门4 分钟阅读发布于 2026年9月1日更新于 2026年9月15日
文章目录
  1. Z 函数是什么
  2. Z 函数代码
  3. 后缀数组是什么
  4. 后缀数组适合什么问题
  5. 字符串哈希和后缀数组怎么选
  6. 我的分析
  7. 面试题
知识目录数据结构与算法:从基础到工程实践41 / 77
LOCAL NOTE高亮并记笔记
0 / 1000 · 只保存在这台设备
READER NOTESZ 函数与后缀数组入门:从前缀匹配到全局子串关系》的本机笔记

我最开始接触“Z 函数与后缀数组入门:从前缀匹配到全局子串关系”时,先遇到的是这个问题:Z 函数和后缀数组刚接触时都像一堆下标技巧,我花了不少时间才把“前缀匹配”和“后缀排序”对应到真实查询。我没有继续硬记结论,而是把过程画出来,再用一两个最小例子亲手跑通。这篇留下的,就是那次重新梳理后真正帮我想明白的东西。

Z 函数和后缀数组都属于字符串进阶结构。它们不像 KMP 那么常用,但能帮助我们理解“字符串和自身前缀的关系”以及“所有后缀之间的关系”。

Z 函数与后缀数组观察字符串的两种方式

Z 函数是什么

对字符串 sz[i] 表示从位置 i 开始的后缀与整个字符串前缀的最长公共前缀长度。

s = a a b a a b a
z = 0 1 0 4 1 0 1

它可以用来做模式匹配。把 pattern + '#' + text 拼起来,如果某个位置的 Z 值等于模式串长度,就说明匹配成功。

Z 函数代码

int[] zFunction(String s) {
    int n = s.length();
    int[] z = new int[n];
    int left = 0, right = 0;
    for (int i = 1; i < n; i++) {
        if (i <= right) {
            z[i] = Math.min(right - i + 1, z[i - left]);
        }
        while (i + z[i] < n && s.charAt(z[i]) == s.charAt(i + z[i])) {
            z[i]++;
        }
        if (i + z[i] - 1 > right) {
            left = i;
            right = i + z[i] - 1;
        }
    }
    return z;
}

这里 [left, right] 表示当前已知的、与前缀匹配的一段最右区间。

后缀数组是什么

后缀数组把字符串的所有后缀按字典序排序。

s = banana

后缀:
0 banana
1 anana
2 nana
3 ana
4 na
5 a

排序后:
5 a
3 ana
1 anana
0 banana
4 na
2 nana

后缀数组常和 LCP 数组一起使用。LCP 表示排序后相邻后缀的最长公共前缀。

后缀数组适合什么问题

问题 思路
最长重复子串 排序后相邻后缀 LCP 最大值
子串出现次数 二分找到匹配区间
字典序第 k 小子串 后缀排序 + 去重统计
两个字符串最长公共子串 拼接后建后缀数组,再看不同来源后缀的 LCP

字符串哈希和后缀数组怎么选

字符串哈希实现简单,适合快速判断子串相等;但哈希存在冲突风险。后缀数组更系统,适合做全局子串关系分析,但实现和理解成本更高。

工程中,如果是普通业务匹配,往往不会手写后缀数组;如果是算法学习、文本分析、DNA 序列这类需求,后缀结构会更有价值。

我的分析

Z 函数像 KMP 的兄弟,重点在“当前后缀和前缀能匹配多长”。后缀数组则更像字符串的全局索引,把所有后缀统一排序后,很多子串问题就变成相邻比较。

这篇不要求一口气手写完整后缀数组倍增算法,先理解它解决什么问题更重要。

面试题

  1. Z 函数和 KMP 都能匹配字符串,它们的视角有什么不同?
  2. 后缀数组为什么能解决最长重复子串?
  3. LCP 数组表示什么?
  4. 字符串哈希和后缀数组各有什么优缺点?
  5. 为什么后缀数组常用于全局子串关系问题?
JARVIS · 当前文章

有哪里没看懂?可以只问这篇。

Jarvis 会限定在《Z 函数与后缀数组入门:从前缀匹配到全局子串关系》及其公开关联内容中检索,并把引用定位回原文章节。

JARVIS / ARTICLE针对《Z 函数与后缀数组入门:从前缀匹配到全局子串关系》提问
当前范围Z 函数与后缀数组入门:从前缀匹配到全局子串关系不会悄悄扩大到全站
0 / 1000

准备好了。当前只会围绕Z 函数与后缀数组入门:从前缀匹配到全局子串关系回答。

READER SIGNAL

这篇内容对你有帮助吗?

不需要登录。你的反馈会直接进入作者待处理列表。