This documentation is automatically generated by online-judge-tools/verification-helper
#include "Src/Sequence/Manacher.hpp"
長さ $N$ の列 $A$ に対して以下の要件を満たす $2N - 1$ 要素の列 $(D_1, D_2, \dots, D_{2N - 1})$ を返す。
template <std::integral RES = usize, std::equality_comparable T = char, class C = std::string>
requires concepts::Container<C, T>
RES
は返り値の型usize
やint
など。
#pragma once
#include <concepts>
#include <optional>
#include <vector>
#include <string>
#include "../Template/TypeAlias.hpp"
namespace zawa {
namespace concepts {
template <class C, class T>
concept Container = requires (C c, usize idx) {
{ c[idx] } -> std::convertible_to<T>;
};
} // namespace concepts
namespace internal {
// ref: https://snuke.hatenablog.com/entry/2014/12/02/235837
template <std::equality_comparable T, std::integral RES>
std::vector<RES> Manacher(const std::vector<std::optional<T>>& a) {
std::vector<RES> res(a.size());
for (usize i = 0, j = 0 ; i < a.size() ; ) {
// i + jはここでしか増加せず、i + jは高々|a|しか増えない
// -> このループは高々|a|
while (i >= j and i + j < a.size() and a[i - j] == a[i + j]) j++;
res[i] = j;
usize k = 1;
// iは高々|a|までしか増えない->kを増やしているこのループは丁度|a|
for ( ; i >= k and k + res[i - k] < j ; k++) res[i + k] = res[i - k];
i += k;
j -= k;
}
for (usize i = 0 ; i < res.size() ; i++) {
if (i & 1) {
res[i] = res[i] & (res[i] ^ 1);
}
else {
res[i] = (res[i] & 1 ? res[i] : res[i] - 1);
}
}
return res;
}
} // namespace internal
template <std::integral RES = usize, std::equality_comparable T = char, class C = std::string>
requires concepts::Container<C, T>
std::vector<RES> Manacher(C a) {
if (a.empty()) return {};
std::vector<std::optional<T>> seq(2 * a.size() - 1);
for (usize i = 0 ; i < a.size() ; i++) {
seq[2 * i] = std::optional{std::move(a[i])};
}
return internal::Manacher<T, RES>(seq);
}
} // namespace zawa
#line 2 "Src/Sequence/Manacher.hpp"
#include <concepts>
#include <optional>
#include <vector>
#include <string>
#line 2 "Src/Template/TypeAlias.hpp"
#include <cstdint>
#include <cstddef>
namespace zawa {
using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using i128 = __int128_t;
using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
using usize = std::size_t;
} // namespace zawa
#line 9 "Src/Sequence/Manacher.hpp"
namespace zawa {
namespace concepts {
template <class C, class T>
concept Container = requires (C c, usize idx) {
{ c[idx] } -> std::convertible_to<T>;
};
} // namespace concepts
namespace internal {
// ref: https://snuke.hatenablog.com/entry/2014/12/02/235837
template <std::equality_comparable T, std::integral RES>
std::vector<RES> Manacher(const std::vector<std::optional<T>>& a) {
std::vector<RES> res(a.size());
for (usize i = 0, j = 0 ; i < a.size() ; ) {
// i + jはここでしか増加せず、i + jは高々|a|しか増えない
// -> このループは高々|a|
while (i >= j and i + j < a.size() and a[i - j] == a[i + j]) j++;
res[i] = j;
usize k = 1;
// iは高々|a|までしか増えない->kを増やしているこのループは丁度|a|
for ( ; i >= k and k + res[i - k] < j ; k++) res[i + k] = res[i - k];
i += k;
j -= k;
}
for (usize i = 0 ; i < res.size() ; i++) {
if (i & 1) {
res[i] = res[i] & (res[i] ^ 1);
}
else {
res[i] = (res[i] & 1 ? res[i] : res[i] - 1);
}
}
return res;
}
} // namespace internal
template <std::integral RES = usize, std::equality_comparable T = char, class C = std::string>
requires concepts::Container<C, T>
std::vector<RES> Manacher(C a) {
if (a.empty()) return {};
std::vector<std::optional<T>> seq(2 * a.size() - 1);
for (usize i = 0 ; i < a.size() ; i++) {
seq[2 * i] = std::optional{std::move(a[i])};
}
return internal::Manacher<T, RES>(seq);
}
} // namespace zawa