Skip to content

online_z_algo.hpp

SECTIONString INCLUDEnoya/string/online_z_algo.hpp

字符逐个加入时在线维护 Z 函数;适合流式字符串的前缀匹配长度。

Complexity: Time: \(O(n)\) total for \(n\) appends with constant-time symbol operations. A single add can be \(O(n)\); query is \(O(1)\). Space: \(O(n)\) state, plus the returned finalized indices.

Source: maspy

AC 记录:zalgorithm。

跳到代码 · GitHub ↗

Implementation

当前头文件,省略 include guard;依赖见 #include。

/// @complexity Time: O(n) total for n appends with constant-time symbol operations.
/// A single add can be O(n); query is O(1).
/// Space: O(n) state, plus the returned finalized indices.

#include <string>
#include <vector>

namespace noya {
/// @brief Online Z-algorithm: compute Z-values incrementally as characters are appended.
template <class S> struct online_z_algo {
  std::vector<std::vector<int>> mp;
  std::vector<int> z;
  std::vector<S> str;
  int p;
  online_z_algo() { p = 1; }

  /// @brief Append c at i == str.size(); return indices fixed by this mismatch.
  /// Positions reaching the current end remain unfinished; index 0 is never emitted.
  /// Input length must fit in int; symbols need coherent != and copying.
  std::vector<int> add(int i, S c) {
    str.push_back(c);
    int len = str.size();
    z.push_back(-1);
    mp.emplace_back();
    std::vector<int> end;

    if (len == 1) {
      return end;
    }

    if (str[0] != c) {
      z[i] = 0;
      end.push_back(i);
    }

    auto del = [&](int j) {
      z[j] = i - j;
      mp[i].push_back(j);
      end.push_back(j);
    };

    while (p <= i) {
      if (z[p] != -1) {
        p += 1;
      } else if (str[i - p] != str[i]) {
        del(p);
        p += 1;
      } else {
        break;
      }
    }
    if (p < i) {
      for (auto j : mp[i - p]) {
        del(j + p);
      }
    }
    return end;
  }

  /// @brief Current longest prefix match at 0 <= i < str.size(); query(0) is the length.
  int query(int i) {
    if (z[i] == -1) {
      return str.size() - i;
    }
    return z[i];
  }
};
} // namespace noya
 // NOYA_ONLINEZALGO_HPP
#ifndef NOYA_ONLINEZALGO_HPP
#define NOYA_ONLINEZALGO_HPP 1

/// @complexity Time: O(n) total for n appends with constant-time symbol operations.
/// A single add can be O(n); query is O(1).
/// Space: O(n) state, plus the returned finalized indices.

#include <string>
#include <vector>

namespace noya {
/// @brief Online Z-algorithm: compute Z-values incrementally as characters are appended.
template <class S> struct online_z_algo {
  std::vector<std::vector<int>> mp;
  std::vector<int> z;
  std::vector<S> str;
  int p;
  online_z_algo() { p = 1; }

  /// @brief Append c at i == str.size(); return indices fixed by this mismatch.
  /// Positions reaching the current end remain unfinished; index 0 is never emitted.
  /// Input length must fit in int; symbols need coherent != and copying.
  std::vector<int> add(int i, S c) {
    str.push_back(c);
    int len = str.size();
    z.push_back(-1);
    mp.emplace_back();
    std::vector<int> end;

    if (len == 1) {
      return end;
    }

    if (str[0] != c) {
      z[i] = 0;
      end.push_back(i);
    }

    auto del = [&](int j) {
      z[j] = i - j;
      mp[i].push_back(j);
      end.push_back(j);
    };

    while (p <= i) {
      if (z[p] != -1) {
        p += 1;
      } else if (str[i - p] != str[i]) {
        del(p);
        p += 1;
      } else {
        break;
      }
    }
    if (p < i) {
      for (auto j : mp[i - p]) {
        del(j + p);
      }
    }
    return end;
  }

  /// @brief Current longest prefix match at 0 <= i < str.size(); query(0) is the length.
  int query(int i) {
    if (z[i] == -1) {
      return str.size() - i;
    }
    return z[i];
  }
};
} // namespace noya
#endif // NOYA_ONLINEZALGO_HPP
/// @complexity Time: O(n) total for n appends with constant-time symbol operations.
/// A single add can be O(n); query is O(1).
/// Space: O(n) state, plus the returned finalized indices.

#include <string>
#include <vector>

namespace noya {
/// @brief Online Z-algorithm: compute Z-values incrementally as characters are appended.
template <class S> struct online_z_algo {
  std::vector<std::vector<int>> mp;
  std::vector<int> z;
  std::vector<S> str;
  int p;
  online_z_algo() { p = 1; }

  /// @brief Append c at i == str.size(); return indices fixed by this mismatch.
  /// Positions reaching the current end remain unfinished; index 0 is never emitted.
  /// Input length must fit in int; symbols need coherent != and copying.
  std::vector<int> add(int i, S c) {
    str.push_back(c);
    int len = str.size();
    z.push_back(-1);
    mp.emplace_back();
    std::vector<int> end;

    if (len == 1) {
      return end;
    }

    if (str[0] != c) {
      z[i] = 0;
      end.push_back(i);
    }

    auto del = [&](int j) {
      z[j] = i - j;
      mp[i].push_back(j);
      end.push_back(j);
    };

    while (p <= i) {
      if (z[p] != -1) {
        p += 1;
      } else if (str[i - p] != str[i]) {
        del(p);
        p += 1;
      } else {
        break;
      }
    }
    if (p < i) {
      for (auto j : mp[i - p]) {
        del(j + p);
      }
    }
    return end;
  }

  /// @brief Current longest prefix match at 0 <= i < str.size(); query(0) is the length.
  int query(int i) {
    if (z[i] == -1) {
      return str.size() - i;
    }
    return z[i];
  }
};
} // namespace noya
 // NOYA_ONLINEZALGO_HPP