【题目链接】
【前置技能】
【题解】
【代码】
#include
#define INF 0x3f3f3f3f
#define LL long long
#define MAXN 500010
using namespace std;
int n, sa[MAXN], rnk[MAXN], hei[MAXN];
char s[MAXN];
template <typename T> void chkmin(T &x, T y){x = min(x, y);}
template <typename T> void chkmax(T &x, T y){x = max(x, y);}
template <typename T> void read(T &x){
x = 0; int f = 1; char ch = getchar();
while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
while (isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();}
x *= f;
}
void suffix(int n){
static int x[MAXN], y[MAXN], rk[MAXN], cnt[MAXN];
memset(cnt, 0, sizeof(cnt));
for (int i = 1; i <= n; ++i)
++cnt[s[i] - 'a'];
for (int i = 1; i < 26; ++i)
cnt[i] += cnt[i - 1];
for (int i = n; i >= 1; --i)
sa[cnt[s[i] - 'a']--] = i;
rnk[sa[1]] = 1;
for (int i = 2; i <= n; ++i)
rnk[sa[i]] = rnk[sa[i - 1]] + (s[sa[i]] != s[sa[i - 1]]);
for (int len = 1; rnk[sa[n]] != n; len <<= 1){
for (int i = 1; i <= n; ++i)
x[i] = rnk[i], y[i] = (i + len <= n) ? rnk[i + len] : 0;
memset(cnt, 0, sizeof(cnt));
for (int i = 1; i <= n; ++i)
++cnt[y[i]];
for (int i = 1; i <= n; ++i)
cnt[i] += cnt[i - 1];
for (int i = n; i >= 1; --i)
rk[cnt[y[i]]--] = i;
memset(cnt, 0, sizeof(cnt));
for (int i = 1; i <= n; ++i)
++cnt[x[i]];
for (int i = 1; i <= n; ++i)
cnt[i] += cnt[i - 1];
for (int i = n; i >= 1; --i)
sa[cnt[x[rk[i]]]--] = rk[i];
rnk[sa[1]] = 1;
for (int i = 2; i <= n; ++i)
rnk[sa[i]] = rnk[sa[i - 1]] + (x[sa[i]] != x[sa[i - 1]] || y[sa[i]] != y[sa[i - 1]]);
}
}
void gethei(int n){
int cur = 0;
for (int i = 1; i <= n; ++i){
if (cur) --cur;
for (int j = sa[rnk[i] + 1]; s[i + cur] == s[j + cur]; ++cur) ;
hei[rnk[i]] = cur;
}
}
struct Segment_Tree{
struct info{int ls, rs, ans;}a[MAXN * 2];
int b[MAXN];
int n, root, cnt;
void build(int &pos, int l, int r){
pos = ++cnt; a[pos].ans = n;
if (l == r) return;
int mid = (l + r) >> 1;
build(a[pos].ls, l, mid);
build(a[pos].rs, mid + 1, r);
}
void init(int x){
n = x, cnt = root = 0;
build(root, 1, n);
}
void push_down(int pos, int l, int r){
if (l == r) {
b[l] = a[pos].ans;
return;
}
int mid = (l + r) >> 1;
chkmin(a[a[pos].ls].ans, a[pos].ans);
chkmin(a[a[pos].rs].ans, a[pos].ans);
push_down(a[pos].ls, l, mid);
push_down(a[pos].rs, mid + 1, r);
}
void push_down(){
push_down(root, 1, n);
}
void modify(int pos, int l, int r, int ll, int rr, int d){
if (l == ll && r == rr){
chkmin(a[pos].ans, d);
return;
}
int mid = (l + r) >> 1;
if (rr <= mid) modify(a[pos].ls, l, mid, ll, rr, d);
else if (ll > mid) modify(a[pos].rs, mid + 1, r, ll, rr, d);
else {
modify(a[pos].ls, l, mid, ll, mid, d);
modify(a[pos].rs, mid + 1, r, mid + 1, rr, d);
}
}
void modify(int l, int r, int d){
modify(root, 1, n, l, r, d);
}
}sgt[2];
int main(){
scanf("%s", s + 1);
n = strlen(s + 1);
suffix(n);
gethei(n);
sgt[0].init(n);
sgt[1].init(n);
for (int i = 1; i <= n; ++i){
int cur = max(hei[rnk[i]], hei[rnk[i] - 1]) + 1;
if (i + cur - 1 <= n) sgt[0].modify(i, i + cur - 1, cur);
if (i + cur - 1 < n) sgt[1].modify(i + cur, n, 1 - i);
}
sgt[0].push_down();
sgt[1].push_down();
for (int i = 1; i <= n; ++i)
printf("%d\n", min(sgt[0].b[i], sgt[1].b[i] + i));
return 0;
}