1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| #include <cstdio> #include <algorithm> using namespace std; template <class Type> void read(Type &x) { char c; bool flag = false; while ((c = getchar()) < '0' || c > '9') c == '-' && (flag = true); x = c - '0'; while ((c = getchar()) >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0'; if (flag) x = ~x + 1; } template <class Type, class ...rest> void read(Type &x, rest &...y) { read(x), read(y...); } template <class Type> void write(Type x) { if (x < 0) putchar('-'), x = ~x + 1; if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <class Type> void chkmax (Type &x, Type k) { if (k > x) x = k; } template <class Type> void chkmin (Type &x, Type k) { if (k < x) x = k; } typedef long long LL; const LL Inf = 1e18; const int N = 6e5 + 10, inf = 1e9; struct Node { int s[2], l, r, mx, mn; } tr[N]; char str[N]; int top, stk[N]; LL s[N], mx[N]; int n, w[N], m, sa[N], rnk[N], ht[N], x[N], y[N], c[N]; void bucsort () { for (int i = 1; i <= m; ++i) c[i] = 0; for (int i = 1; i <= n; ++i) ++c[x[i]]; for (int i = 2; i <= m; ++i) c[i] += c[i - 1]; for (int i = n; i; i--) sa[c[x[y[i]]]--] = y[i]; } void init () { for (int i = 1; i <= n; ++i) x[i] = str[i] - 'a' + 1, y[i] = i, sa[i] = 0; bucsort(); for (int k = 1; k <= n; k <<= 1) { int cnt = 0; for (int i = n - k + 1; i <= n; ++i) y[++cnt] = i; for (int i = 1; i <= n; ++i) if (sa[i] > k) y[++cnt] = sa[i] - k; bucsort(); for (int i = 1; i <= n; ++i) y[i] = x[i]; x[sa[1]] = cnt = 1; for (int i = 2; i <= n; ++i) x[sa[i]] = cnt += (y[sa[i]] ^ y[sa[i - 1]] || y[sa[i] + k] ^ y[sa[i - 1] + k]); if ((m = cnt) == n) break; } for (int i = 1; i <= n; ++i) rnk[sa[i]] = i; for (int i = 1, k = 0; i <= n; ++i) { int j = sa[rnk[i] - 1]; if (k) --k; while (str[i + k] == str[j + k]) ++k; ht[rnk[i]] = k; } } void calc (int x) { tr[x].l = tr[x].r = x; tr[x].mx = -inf, tr[x].mn = inf; if (tr[x].s[0]) calc(tr[x].s[0]), tr[x].l = tr[tr[x].s[0]].l; if (tr[x].s[1]) calc(tr[x].s[1]), tr[x].r = tr[tr[x].s[1]].r; chkmax(tr[x].mx, tr[tr[x].s[0]].mx), chkmin(tr[x].mn, tr[tr[x].s[0]].mn); chkmax(tr[x].mx, tr[tr[x].s[1]].mx), chkmin(tr[x].mn, tr[tr[x].s[1]].mn); s[ht[x]] += (LL)(tr[x].r - x + 1) * (x - tr[x].l + 1); chkmax(mx[ht[x]], (LL)max(tr[tr[x].s[0]].mx, w[sa[tr[x].l - 1]]) * max(w[sa[x]], tr[tr[x].s[1]].mx)); chkmax(mx[ht[x]], (LL)min(tr[tr[x].s[0]].mn, w[sa[tr[x].l - 1]]) * min(w[sa[x]], tr[tr[x].s[1]].mn)); chkmax(tr[x].mx, w[sa[x]]), chkmin(tr[x].mn, w[sa[x]]); } int main () { m = 26, read(n); if (n == 1) return puts("0 0"), 0; scanf("%s", str + 1); init(); for (int i = 1; i <= n; ++i) read(w[i]); for (int i = 2; i <= n; ++i) { int t = top; while (t && ht[stk[t]] >= ht[i]) --t; if (t) tr[stk[t]].s[1] = i; if (t < top) tr[i].s[0] = stk[t + 1]; stk[top = ++t] = i; } for (int i = 0; i < n; ++i) mx[i] = -Inf; tr[0].mn = inf, tr[0].mx = -inf; calc(stk[1]); for (int i = n - 2; ~i; --i) s[i] += s[i + 1], chkmax(mx[i], mx[i + 1]); for (int i = 0; i < n; ++i) write(s[i]), putchar(' '), write(s[i] ? mx[i] : 0), puts(""); return 0; }
|