XX在進行字符串研究的時候,遇到了一個十分棘手的問題。c++
在這個問題中,給定一個字符串S,與一個整數K,定義S的子串T=S(i, j)是關於第K位的識別子串,知足如下兩個條件:ui
一、i≤K≤j。spa
二、子串T只在S中出現過一次。code
例如,S="banana",K=5,則關於第K位的識別子串有"nana","anan","anana","nan","banan"和"banana"。ip
如今,給定S,XX但願知道對於S的每一位,最短的識別子串長度是多少,請你來幫助他。字符串
僅一行,輸入長度爲N的字符串S。input
輸出N行,每行一個整數,第i行的整數表示對於第i位的最短識別子串長度。it
agoodcookcooksgoodfoodio
1
2
3
3
2
2
3
3
2
2
3
3
2
1
2
3
3
2
1
2
3
4class
N<=5*10^5
首先發現能夠按照每一個後綴統計貢獻
而後直接把每一個後綴和先後排名的串lcp的max:len求出來,這些值是不能更新的
而後對於$[i,i+len] \(用len+1更新,對於\)[i+len,n]$用一個等差數列更新min
等差數列維護直接標記永久化就能夠了
而後注意特判是否是沒有合法的解
#include<bits/stdc++.h> using namespace std; typedef pair<int, int> pi; const int N = 5e5 + 10; const int INF_of_int = 1e9; int typ1[N << 2], typ2[N << 2]; #define LD (t << 1) #define RD (t << 1 | 1) void build(int t, int l, int r) { typ1[t] = INF_of_int; typ2[t] = -INF_of_int; if (l == r) return; int mid = (l + r) >> 1; build(LD, l, mid); build(RD, mid + 1, r); } void modify(int t, int l, int r, int ql, int qr, int typ, int val) { if (ql > qr) return; if (ql <= l && r <= qr) { if (typ == 1) { typ1[t] = min(typ1[t], val); } else { typ2[t] = max(typ2[t], val); } return; } int mid = (l + r) >> 1; if (qr <= mid) modify(LD, l, mid, ql, qr, typ, val); else if (ql > mid) modify(RD, mid + 1, r, ql, qr, typ, val); else { modify(LD, l, mid, ql, mid, typ, val); modify(RD, mid + 1, r, mid + 1, qr, typ, val); } } void output(int t, int l, int r, int val, int pos) { if (typ1[t]) val = min(val, typ1[t]); if (typ2[t]) val = min(val, pos - typ2[t] + 1); if (l == r) { printf("%d\n", val); return; } int mid = (l + r) >> 1; if (pos <= mid) output(LD, l, mid, val, pos); else output(RD, mid + 1, r, val, pos); } struct Suffix_Array { int s[N], n, m; int c[N], x[N], y[N]; int sa[N], rank[N], height[N]; void init(int len, char *c) { n = len, m = 0; for (int i = 1; i <= n; i++) { s[i] = c[i]; m = max(m, s[i]); } } void radix_sort() { for (int i = 1; i <= m; i++) c[i] = 0; for (int i = 1; i <= n; i++) c[x[y[i]]]++; for (int i = 1; i <= m; i++) c[i] += c[i - 1]; for (int i = n; i >= 1; i--) sa[c[x[y[i]]]--] = y[i]; } void buildsa() { for (int i = 1; i <= n; i++) x[i] = s[i], y[i] = i; radix_sort(); int now; for (int k = 1; k <= n; k <<= 1) { now = 0; for (int i = n - k + 1; i <= n; i++) y[++now] = i; for (int i = 1; i <= n; i++) if (sa[i] > k) y[++now] = sa[i] - k; radix_sort(); y[sa[1]] = now = 1; for (int i = 2; i <= n; i++) y[sa[i]] = (x[sa[i]] == x[sa[i - 1]] && x[sa[i] + k] == x[sa[i - 1] + k]) ? now : ++now; swap(x, y); if (now == n) break; m = now; } } void buildrank() { for (int i = 1; i <= n; i++) rank[sa[i]] = i; } void buildheight() { for (int i = 1; i <= n; i++) { int k = max(height[rank[i - 1]] - 1, 0); for (; s[i + k] == s[sa[rank[i] - 1] + k]; k++); height[rank[i]] = k; } } void build(int len, char *c) { init(len, c); buildsa(); buildrank(); buildheight(); } void solve() { for (int i = 1; i <= n; i++) { int len = max(height[rank[i]], height[rank[i] + 1]); if (i + len > n) continue; modify(1, 1, n, i, i + len, 1, len + 1); modify(1, 1, n, i + len, n, 2, i); } } } Sa; int len; char s[N]; int main() { #ifdef dream_maker freopen("input.txt", "r", stdin); #endif scanf("%s", s + 1); len = strlen(s + 1); Sa.build(len, s); build(1, 1, len); Sa.solve(); for (int i = 1; i <= len; i++) output(1, 1, len, len, i); return 0; }