Competitive programming demands a high degree of code reusability. Below is a curated set of templates that have been fine-tuned for typical on line judges, including a comprehensive header, fast input/output routines, a modular arithmetic wrapper, and implementations of the suffix automaton and suffix array.
Compact Header with Utilities
namespace cp_core {
#ifndef ONLINE_JUDGE
#define LOCAL_BUILD
#define FILE_REDIRECT
#endif
#define ENABLE_FAST_IO
#ifdef ENABLE_FAST_IO
char io_buf[1 << 20], *read_ptr = io_buf, *write_ptr = io_buf;
#define next_char() (read_ptr == write_ptr && (write_ptr = (read_ptr = io_buf) + fread(io_buf, 1, 1 << 20, stdin)) ? EOF : *read_ptr++)
#else
#define next_char() getchar()
#endif
using i64 = long long;
using u64 = unsigned long long;
using f64 = double;
using ld = long double;
using pii = std::pair<int, int>;
#ifdef FILE_REDIRECT
struct FileRedirect {
FileRedirect(const std::string &problem) {
freopen((problem + ".in").c_str(), "r", stdin);
freopen((problem + ".out").c_str(), "w", stdout);
}
} redirect_instance("problem");
#endif
#define pub push_back
#define pob pop_back
template<typename T>
std::ostream& operator<<(std::ostream &os, const std::vector<T> &vec) {
if (vec.empty()) return os << "{}";
os << '{' << vec.front();
for (std::size_t i = 1; i < vec.size(); ++i) os << ',' << vec[i];
return os << '}';
}
template<typename T> void set_min(T &a, T b) { if (a > b) a = b; }
template<typename T> void set_max(T &a, T b) { if (a < b) a = b; }
template<typename T>
void log_value(const char *label, T value) {
#ifdef LOCAL_BUILD
std::cerr << label << '=' << value << '\n';
#endif
}
template<typename T, typename... Ts>
void log_value(const char *label, T first, Ts... rest) {
#ifdef LOCAL_BUILD
while (*label != ',') std::cerr << *label++;
std::cerr << '=' << first << ',';
log_value(label + 1, rest...);
#endif
}
#define LOG(...) log_value(#__VA_ARGS__, __VA_ARGS__)
template<typename T = int>
T scan() {
char c = next_char(); bool negative = false; T x = 0;
while (c < 48 || c > 57) { if (c == '-') negative = true; c = next_char(); }
for (; c >= 48 && c <= 57; c = next_char()) x = (x << 1) + (x << 3) + (c ^ 48);
return negative ? -x : x;
}
template<typename T>
void scan(T &x) {
char c = next_char(); bool negative = false; x = 0;
while (c < 48 || c > 57) { if (c == '-') negative = true; c = next_char(); }
for (; c >= 48 && c <= 57; c = next_char()) x = (x << 1) + (x << 3) + (c ^ 48);
if (negative) x = -x;
}
template<typename T, typename... Ts>
void scan(T &first, Ts&... rest) { scan(first); scan(rest...); }
}
Modular Arithmetic (modint)
A lightweight wrapper that supports addition, subtraction, multiplication, and division under a global modulus MOD.
constexpr int MOD = 1e9 + 7;
struct ModInt {
int value;
ModInt(int x = 0) : value(x % MOD + (x < 0) * MOD) {}
ModInt operator+(const ModInt &o) const { return (value + o.value) % MOD; }
ModInt operator-(const ModInt &o) const { return (value - o.value + MOD) % MOD; }
ModInt operator*(const ModInt &o) const { return static_cast<long long>(value) * o.value % MOD; }
ModInt operator/(const ModInt &o) const {
int exponent = MOD - 2;
ModInt result{1}, base = o;
while (exponent) {
if (exponent & 1) result = result * base;
base = base * base;
exponent >>= 1;
}
return *this * result;
}
ModInt operator-() const { return MOD - value; }
ModInt& operator+=(const ModInt &o) { return *this = *this + o; }
ModInt& operator-=(const ModInt &o) { return *this = *this - o; }
ModInt& operator*=(const ModInt &o) { return *this = *this * o; }
ModInt& operator/=(const ModInt &o) { return *this = *this / o; }
bool operator==(const ModInt &o) const { return value == o.value; }
bool operator!=(const ModInt &o) const { return value != o.value; }
};
Simple Integer Readers
Two classic handwritten parsers: one for unsigned inputs and one that detects a leading minus sign.
int read_int() {
char c; while ((c = getchar()) < 48 || c > 57);
int x = 0;
do { x = (x << 1) + (x << 3) + (c ^ 48); } while ((c = getchar()) >= 48 && c <= 57);
return x;
}
int read_signed_int() {
char c; while ((c = getchar()) < 48 || c > 57) { if (c == '-') break; }
bool negative = false;
if (c == '-') { negative = true; c = getchar(); }
int x = 0;
do { x = (x << 1) + (x << 3) + (c ^ 48); } while ((c = getchar()) >= 48 && c <= 57);
return negative ? -x : x;
}
Fast I/O with Custom Buffer
By bypassing standard library buffering we achieve faster parsing.
#define CIN_CHAR() (p1 == p2 && (p2 = (p1 = cin_buf) + fread(cin_buf, 1, 1 << 21, stdin)) ? EOF : *p1++)
char cin_buf[1 << 21], *p1 = cin_buf, *p2 = cin_buf;
int fast_read() {
char c = CIN_CHAR();
while (c < 48 || c > 57) c = CIN_CHAR();
int x = 0;
do { x = (x << 1) + (x << 3) + (c ^ 48); c = CIN_CHAR(); } while (c >= 48 && c <= 57);
return x;
}
int fast_read_signed() {
char c = CIN_CHAR(); bool neg = false;
while (c < 48 || c > 57) { if (c == '-') neg = true; c = CIN_CHAR(); }
int x = 0;
do { x = (x << 1) + (x << 3) + (c ^ 48); c = CIN_CHAR(); } while (c >= 48 && c <= 57);
return neg ? -x : x;
}
Suffix Automaton
A compact suffix automaton that computes end‑position cardinalities for each state.
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 1000003;
char str[MAXN];
int nxt[MAXN][26], len[MAXN], link[MAXN], cnt[MAXN];
int bucket[MAXN], order[MAXN];
int last = 1, nodes = 1, n;
void sam_extend(int ch) {
int cur = ++nodes, p = last;
len[cur] = len[p] + 1;
cnt[cur] = 1;
while (p && !nxt[p][ch]) { nxt[p][ch] = cur; p = link[p]; }
if (!p) { link[cur] = 1; last = cur; return; }
int q = nxt[p][ch];
if (len[q] == len[p] + 1) { link[cur] = q; last = cur; return; }
int clone = ++nodes;
len[clone] = len[p] + 1;
link[clone] = link[q];
memcpy(nxt[clone], nxt[q], sizeof(nxt[0]));
link[q] = link[cur] = clone;
while (p && nxt[p][ch] == q) { nxt[p][ch] = clone; p = link[p]; }
last = cur;
}
void build_sam() {
scanf("%s", str);
n = strlen(str);
for (int i = 0; i < n; ++i) sam_extend(str[i] - 'a');
for (int i = 1; i <= nodes; ++i) ++bucket[len[i]];
for (int i = 1; i <= n; ++i) bucket[i] += bucket[i - 1];
for (int i = nodes; i; --i) order[bucket[len[i]]--] = i;
for (int i = nodes; i; --i) {
int node = order[i];
cnt[link[node]] += cnt[node];
}
}
Suffix Array (O(n log n) prefix doubling)
An in‑place implementation of the prefix‑doubling algorithm that computes the suffix array, rank array, and LCP array without extra sorting.
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 200003;
char s[N];
int n, w, p;
int buc[N], sa[N], rk[N], old_rk[N << 1], tmp[N];
int lcp[N];
bool same_rank(int a, int b) {
return old_rk[a] == old_rk[b] && old_rk[a + w] == old_rk[b + w];
}
void build_sa(int alphabet) {
memset(buc + 1, 0, alphabet << 2);
for (int i = 1; i <= n; ++i) ++buc[rk[i] = s[i]];
for (int i = 1; i <= alphabet; ++i) buc[i] += buc[i - 1];
for (int i = n; i; --i) sa[buc[rk[i]]--] = i;
for (w = 1, p = 0; ; w <<= 1, p = 0) {
for (int i = n; i > n - w; --i) tmp[++p] = i;
for (int i = 1; i <= n; ++i) if (sa[i] > w) tmp[++p] = sa[i] - w;
memset(buc + 1, 0, alphabet << 2);
for (int i = 1; i <= n; ++i) ++buc[rk[tmp[i]]];
for (int i = 1; i <= alphabet; ++i) buc[i] += buc[i - 1];
for (int i = n; i; --i) sa[buc[rk[tmp[i]]]--] = tmp[i];
memcpy(old_rk + 1, rk + 1, n << 2);
p = rk[sa[1]] = 1;
for (int i = 2; i <= n; ++i) {
rk[sa[i]] = same_rank(sa[i], sa[i - 1]) ? p : ++p;
}
if (p == n) break;
alphabet = p;
}
for (int i = 1, k = 0; i <= n; ++i) {
if (rk[i] == 1) { k = 0; continue; }
if (k) --k;
while (i + k <= n && sa[rk[i] - 1] + k <= n && s[i + k] == s[sa[rk[i] - 1] + k]) ++k;
lcp[rk[i] - 1] = k;
}
}