题目传送门
双倍经验传送门
解法全靠yy……
#include
#define inf 1 << 30
#define N 500010
using namespace std;
struct Node {
int x, id;
bool operator > (const Node &a) const {return x > a.x;}
bool operator < (const Node &a) const {return x < a.x;}
bool operator == (const Node &a) const {return x == a.x && id == a.id;}
};
struct SegmentTree {
int mn[N * 4];
#define lc k << 1
#define rc k << 1 | 1
void build(int k, int l, int r) {
if (l == r) return mn[k] = inf, void();
int mid = (l + r) >> 1;
build(lc, l, mid), build(rc, mid + 1, r);
}
void modify(int k, int l, int r, int x, int v) {
if (l == r) return mn[k] = v, void();
int mid = (l + r) >> 1;
if (x <= mid) modify(lc, l, mid, x, v);
else modify(rc, mid + 1, r, x, v);
mn[k] = min(mn[lc], mn[rc]);
}
int query(int k, int l, int r, int L, int R) {
if (L <= l && r <= R) return mn[k];
int mid = (l + r) >> 1, ret = inf;
if (L <= mid) ret = min(ret, query(lc, l, mid, L, R));
if (R > mid) ret = min(ret, query(rc, mid + 1, r, L, R));
return ret;
}
} T;
char st[N];
int n, m, s[N], y[N], ht[N], sa[N], len[N], rnk[N];
void Sort() {
for (int i = 1; i <= m; i++) s[i] = 0;
for (int i = 1; i <= n; i++) s[rnk[i]]++;
for (int i = 1; i <= m; i++) s[i] += s[i - 1];
for (int i = n; i; i--) sa[s[rnk[y[i]]]--] = y[i];
}
void build() {
n = strlen(st + 1), m = 200;
for (int i = 1; i <= n; i++) rnk[i] = st[i], y[i] = i;
Sort(); int len = 0;
for (int k = 1; k <= n; k <<= 1, m = len, len = 0) {
for (int i = n - k + 1; i <= n; i++) y[++len] = i;
for (int i = 1; i <= n; i++) if (sa[i] > k) y[++len] = sa[i] - k;
Sort(), swap(rnk, y), rnk[sa[1]] = len = 1;
for (int i = 2; i <= n; i++)
rnk[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? len : ++len;
if (len >= n) break;
}
for (int i = 1, k = 0; i <= n; i++) {
if (k) k--; int j = sa[rnk[i] - 1];
while (st[i + k] == st[j + k]) k++;
ht[rnk[i]] = k;
}
}
int main() {
cin >> st + 1; build();
for (int i = 1; i <= n; i++) {
int pos = rnk[i];
len[i] = max(ht[pos], ht[pos + 1]);
}
T.build(1, 1, n); int mx = -inf;
priority_queue <Node, vector <Node>, greater <Node> > h1, d1;
priority_queue <Node, vector <Node>, less <Node> > h2, d2;
for (int i = 1; i <= n; i++) {
h1.push((Node) {i + len[i], i});
h2.push((Node) {i + len[i], i});
T.modify(1, 1, n, i, len[i] + 1);
while (true) {
while (!d1.empty() && h1.top() == d1.top()) h1.pop(), d1.pop();
if (h1.empty()) break; Node tmp = h1.top();
if (tmp.x >= i) break; h1.pop(), d2.push(tmp);
int x = tmp.id; mx = max(mx, x), T.modify(1, 1, n, x, inf);
}
while (true) {
while (!d2.empty() && h2.top() == d2.top()) h2.pop(), d2.pop();
if (h2.empty()) break; Node tmp = h2.top();
if (tmp.x <= n) break; h2.pop(), d1.push(tmp);
int x = tmp.id; T.modify(1, 1, n, x, inf);
}
int ans = min(T.query(1, 1, n, 1, i), i - mx + 1);
cout << ans << '\n';
}
return 0;
}