tml
tml
struct suffixArray {
vector <int> sa;
vector <int> pos;
vector <int> lcp;
int N;
string S;
void buildSA() {
vector <int> tmp(N);
int gap;
auto cmp = [&](int i, int j) {
if (pos[i] != pos[j]) return pos[i] < pos[j];
i += gap;
j += gap;
if (i < N && j < N) return pos[i] < pos[j];
return i > j;
};
for (gap = 1; ; gap <<= 1) {
sort(all(sa), cmp);
for (int i = 0; i < N - 1; i++) tmp[i + 1] = tmp[i] +
cmp(sa[i], sa[i + 1]);
for (int i = 0; i < N; i++) pos[sa[i]] = tmp[i];
if (tmp[N - 1] == N - 1) break;
}
}
void buildLCP() {
for (int i = 0, k = 0; i < N; i++) {
if (pos[i] != N - 1) {
for (int j = sa[pos[i] + 1]; S[i + k] == S[j +
k]; ) ++k;
lcp[pos[i]] = k;
if (k) --k;
}
}
}
};
lineContainer
/**
* Author: Simon Lindholm
* Date: 2017-04-20
* License: CC0
* Source: own work
* Description: Container where you can add lines of the form kx+m, and query
maximum values at points x.
* Useful for dynamic programming (``convex hull trick'').
* Time: O(\log N)
* Status: stress-tested
*/
#pragma once
struct Line {
mutable ll k, m, p;
bool operator<(const Line& o) const { return k < o.k; }
bool operator<(ll x) const { return p < x; }
};
Hungarian
namespace HungarianAlgo {
const int inf = 1e9;
const int MAXN = 201, MAXM = 201;
int findPath() {
while (q.size()) {
int u = q.front();
q.pop();
for (int v = 1; v <= M; v++) {
if (trace[v]) continue;
if (getC(u, v) == 0) {
trace[v] = u;
if (matchY[v] == 0) return v;
q.push(matchY[v]);
}
if (d[v] > getC(u, v)) {
d[v] = getC(u, v);
lnk[v] = u;
}
}
}
return 0;
}
void changeWeight() {
int delta = inf;
for (int i = 1; i <= M; i++) if (trace[i] == 0) delta = min(delta,
d[i]);
fx[startV] += delta;
for (int i = 1; i <= M; i++) {
if (trace[i]) {
fx[matchY[i]] += delta;
fy[i] -= delta;
} else {
d[i] -= delta;
if (d[i] == 0) {
trace[i] = lnk[i];
if (!matchY[i]) endV = i;
else q.push(matchY[i]);
}
}
}
}
void enLarge(int t) {
while (t) {
int s = trace[t];
int k = matchX[s];
matchX[s] = t;
matchY[t] = s;
t = k;
}
}
ll minimumMatching() {
for (startV = 1; startV <= N; startV++) {
while (q.size()) q.pop();
q.push(startV);
for (int i = 1; i <= M; i++) {
trace[i] = 0;
d[i] = getC(startV, i);
lnk[i] = startV;
}
endV = 0;
while (!endV) {
endV = findPath();
if (!endV) changeWeight();
}
enLarge(endV);
}
ll ans = 0;
for (int i = 1; i <= N; i++) {
ans += c[i][matchX[i]];
if (ans >= inf) return -1;
}
return ans;
}
void print() {
for (int i = 1; i <= N; i++) cout << -fx[i] << ' ';
cout << '\n';
for (int i = 1; i <= M; i++) cout << -fy[i] << ' ';
}
}