Skip to content

lyndon_factor.hpp

SECTIONString INCLUDEnoya/string/lyndon_factor.hpp

用 Duval 算法把序列唯一分解为字典序非增的 Lyndon 串,返回含 0 和 \(n\) 的边界;字符串直接遍历,空输入返回单个 0。

Complexity: Time: \(O(n)\), for constant-time coherent comparisons. Space: \(O(f + 1)\) returned boundaries and \(O(1)\) auxiliary space, for \(f\) factors.

AC 记录:lyndon_factorization。

跳到代码 · GitHub ↗

Implementation

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

/// @complexity Time: O(n), for constant-time coherent comparisons.
/// Space: O(f + 1) returned boundaries and O(1) auxiliary space, for f factors.

#include <string>
#include <vector>

namespace noya {

namespace lyndon_internal {
template <class Seq> std::vector<int> factor(const Seq &s) {
  int n = int(s.size());
  std::vector<int> res{0};
  for (int i = 0; i < n;) {
    int j = i + 1, k = i;
    for (; j < n && s[k] <= s[j]; j += 1)
      k = s[k] < s[j] ? i : k + 1;
    while (i <= k)
      res.push_back(i += j - k);
  }
  return res;
}
} // namespace lyndon_internal

/// @brief Nonincreasing Lyndon factorization as boundaries including 0 and n.
/// Empty input returns {0}. Symbols use their coherent < and <= ordering.
template <class T> std::vector<int> lyndon(const std::vector<T> &s) {
  return lyndon_internal::factor(s);
}

/// @brief Traverse characters directly, retaining native plain-char ordering.
inline std::vector<int> lyndon(const std::string &s) {
  return lyndon_internal::factor(s);
}

} // namespace noya

 // NOYA_LYNDON_FACTOR_HPP
#ifndef NOYA_LYNDON_FACTOR_HPP
#define NOYA_LYNDON_FACTOR_HPP 1

/// @complexity Time: O(n), for constant-time coherent comparisons.
/// Space: O(f + 1) returned boundaries and O(1) auxiliary space, for f factors.

#include <string>
#include <vector>

namespace noya {

namespace lyndon_internal {
template <class Seq> std::vector<int> factor(const Seq &s) {
  int n = int(s.size());
  std::vector<int> res{0};
  for (int i = 0; i < n;) {
    int j = i + 1, k = i;
    for (; j < n && s[k] <= s[j]; j += 1)
      k = s[k] < s[j] ? i : k + 1;
    while (i <= k)
      res.push_back(i += j - k);
  }
  return res;
}
} // namespace lyndon_internal

/// @brief Nonincreasing Lyndon factorization as boundaries including 0 and n.
/// Empty input returns {0}. Symbols use their coherent < and <= ordering.
template <class T> std::vector<int> lyndon(const std::vector<T> &s) {
  return lyndon_internal::factor(s);
}

/// @brief Traverse characters directly, retaining native plain-char ordering.
inline std::vector<int> lyndon(const std::string &s) {
  return lyndon_internal::factor(s);
}

} // namespace noya

#endif // NOYA_LYNDON_FACTOR_HPP
/// @complexity Time: O(n), for constant-time coherent comparisons.
/// Space: O(f + 1) returned boundaries and O(1) auxiliary space, for f factors.

#include <string>
#include <vector>

namespace noya {

namespace lyndon_internal {
template <class Seq> std::vector<int> factor(const Seq &s) {
  int n = int(s.size());
  std::vector<int> res{0};
  for (int i = 0; i < n;) {
    int j = i + 1, k = i;
    for (; j < n && s[k] <= s[j]; j += 1)
      k = s[k] < s[j] ? i : k + 1;
    while (i <= k)
      res.push_back(i += j - k);
  }
  return res;
}
} // namespace lyndon_internal

/// @brief Nonincreasing Lyndon factorization as boundaries including 0 and n.
/// Empty input returns {0}. Symbols use their coherent < and <= ordering.
template <class T> std::vector<int> lyndon(const std::vector<T> &s) {
  return lyndon_internal::factor(s);
}

/// @brief Traverse characters directly, retaining native plain-char ordering.
inline std::vector<int> lyndon(const std::string &s) {
  return lyndon_internal::factor(s);
}

} // namespace noya

 // NOYA_LYNDON_FACTOR_HPP