显示代码纯文本
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <ctime>
using namespace std;
typedef unsigned long long LL;
const int MAXN = 1e5 + 5;
const int Pri = 9973;
const LL Inf = 1ll << 62;
struct SuffixBalanceTree {
LL tag;
int Son[2], Size, fix;
} Tr[MAXN];
int tot, Root, Lcp[MAXN];
char S[MAXN];
LL Del, Pow[MAXN], Has[MAXN];
bool Cmp(int x, int y) {
return S[x] < S[y] || S[x] == S[y] && Tr[x - 1].tag < Tr[y - 1].tag;
}
void Clear(int x, LL l, LL r) {
Tr[x].fix = rand();
Tr[x].Son[0] = Tr[x].Son[1] = 0;
Tr[x].Size = 1;
Tr[x].tag = (l + r) >> 1;
}
void Update(int Now, LL l, LL r) {
if (!Now) return;
Tr[Now].tag = (l + r) >> 1;
LL Mid = (l + r) >> 1;
Update(Tr[Now].Son[0], l, Mid), Update(Tr[Now].Son[1], Mid + 1, r);
Tr[Now].Size = Tr[Tr[Now].Son[0]].Size + Tr[Tr[Now].Son[1]].Size + 1;
}
void Rotate(int Now, int Pre, LL l, LL r) {
int Side = Tr[Pre].Son[1] == Now;
Tr[Pre].Son[Side] = Tr[Now].Son[Side ^ 1];
Tr[Now].Son[Side ^ 1] = Pre;
Update(Now, l, r);
}
void Insert(int &Now, LL l, LL r) {
if (!Now) {
Now = tot;
Clear(Now, l, r);
return;
}
Tr[Now].Size ++;
LL Mid = (l + r) >> 1;
if (Cmp(tot, Now)) Insert(Tr[Now].Son[0], l, Mid); else
Insert(Tr[Now].Son[1], Mid + 1, r);
if (Tr[tot].fix > Tr[Now].fix) {
Rotate(tot, Now, l, r);
Now = tot;
}
}
int GetRank(int Now) {
if (Now == tot) return Tr[Tr[Now].Son[0]].Size + 1;
if (Cmp(tot, Now)) return GetRank(Tr[Now].Son[0]);
return Tr[Tr[Now].Son[0]].Size + 1 + GetRank(Tr[Now].Son[1]);
}
int Search(int Now, int rk) {
if (!Now) return Now;
if (Tr[Tr[Now].Son[0]].Size + 1 == rk) return Now;
if (Tr[Tr[Now].Son[0]].Size >= rk) return Search(Tr[Now].Son[0], rk);
return Search(Tr[Now].Son[1], rk - Tr[Tr[Now].Son[0]].Size - 1);
}
bool Same(int l1, int l2, int len) {
int r1 = l1 + len - 1, r2 = l2 + len - 1;
return Has[r1] - Has[l1 - 1] * Pow[len] == Has[r2] - Has[l2 - 1] * Pow[len];
}
int TreatLcp(int x, int y) {
int l = 1, r = min(x, y), Ans = 0;
while (l <= r) {
int Mid = (l + r) >> 1;
if (Same(x - Mid + 1, y - Mid + 1, Mid)) Ans = Mid, l = Mid + 1; else
r = Mid - 1;
}
Lcp[y] = Ans;
}
void Add(char c) {
S[++ tot] = c;
Has[tot] = Has[tot - 1] * Pri + S[tot] - 'a' + 1;
Insert(Root, 1, Inf);
int rk = GetRank(Root);
int l = Search(Root, rk - 1), r = Search(Root, rk + 1);
Del = Del - Lcp[r];
TreatLcp(l, tot), TreatLcp(tot, r);
Del = Del + Lcp[tot] + Lcp[r];
}
int Merge(int a, int b) {
if (!a) return b;
if (!b) return a;
if (Tr[a].fix < Tr[b].fix) {
Tr[b].Son[0] = Merge(a, Tr[b].Son[0]);
return b;
}
Tr[a].Son[1] = Merge(Tr[a].Son[1], b);
return a;
}
void Out(int &Now, LL l, LL r) {
if (tot == Now) {
Now = Merge(Tr[Now].Son[0], Tr[Now].Son[1]);
Update(Now, l, r);
} else {
Tr[Now].Size --;
LL Mid = (l + r) >> 1;
if (Cmp(tot, Now)) Out(Tr[Now].Son[0], l, Mid); else
Out(Tr[Now].Son[1], Mid + 1, r);
}
}
void Delete() {
int rk = GetRank(Root);
int l = Search(Root, rk - 1), r = Search(Root, rk + 1);
Del = Del - Lcp[tot] - Lcp[r];
TreatLcp(l, r);
Del = Del + Lcp[r];
Out(Root, 1, Inf);
tot --;
}
int main() {
freopen("hahaha.in","r",stdin);freopen("hahaha.out","w",stdout);
int len;
scanf("%d",&len);
scanf("%s", S + 1);
Pow[0] = 1;
for (int i = 1; i <= len; i ++) Pow[i] = Pow[i - 1] * Pri;
for (int i = 1; i <= len; i ++) {
if (S[i] == '-') Delete(); else
Add(S[i]);
printf("%lld\n", 1ll * tot * (tot + 1) / 2 - Del);
}
}