Z Algorithm

O(n)

z[i] is the length of the longest common prefix of s and s[i..]. Same jobs as the prefix function (matching, borders, periods) with a shape some find easier to reason about. For matching, run it on pattern + '#' + text and look for z values equal to the pattern length.

// use it on

CSES: Finding Borders

A border is a prefix that is also a suffix: position i is a border exactly when i + z[i] equals the string length.

// the code

// z[i] = longest common prefix of s and s.substr(i)
vector<int> z_function(const string& s) {
    int n = s.size();
    vector<int> z(n, 0);
    z[0] = n;
    for (int i = 1, l = 0, r = 0; i < n; i++) {
        if (i < r) z[i] = min(r - i, z[i - l]);
        while (i + z[i] < n && s[z[i]] == s[i + z[i]]) z[i]++;
        if (i + z[i] > r) l = i, r = i + z[i];
    }
    return z;
}