cp-documentation

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub zawa-tin/cp-documentation

:heavy_check_mark: Manacher (Enumerate Palindromes)
(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は返り値の型usizeintなど。

Depends on

Verified with

Code

#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
Back to top page