因为SAM增量法构造的特点,所以每一次增加节点计算就可以了
因为SAM的转移是线性的,所以开个map也是兹辞的
#include<bits/stdc++.h>
using namespace std;
const int maxn = 112345;
struct Node{
int len,fa;
map<int,int> nex;
Node(int _len = 0){
len = _len;
fa = 0;
nex.clear();
}
void copy(const Node & v){
nex = v.nex;
fa = v.fa;
}
bool exist(int x){
return nex.find(x) != nex.end();
}
}node[maxn*2];
int _cnt;
int newNode(int len){
node[_cnt] = Node(len);
return _cnt++;
}
int root,omg;
void init(){
_cnt = 1;
root = omg = newNode(0);
}
void extend(int x){
int ox = newNode(node[omg].len+1);
while(omg && !node[omg].exist(x)){
node[omg].nex[x] = ox;
omg = node[omg].fa;
}
if(!omg) node[ox].fa = root;
else{
int omgx = node[omg].nex[x];
if(node[omg].len + 1 == node[omgx].len) node[ox].fa = omgx;
else{
int ax = newNode(node[omg].len+1);
node[ax].copy(node[omgx]);
node[ox].fa = node[omgx].fa = ax;
while(omg && node[omg].exist(x) && node[omg].nex[x] == omgx){
node[omg].nex[x] = ax;
omg = node[omg].fa;
}
}
}
omg = ox;
}
#define LL long long
int main(){
int n;
while(~scanf("%d",&n)){
LL ans = 0;
init();
int x;
while(n--){
scanf("%d",&x);
extend(x);
ans += node[omg].len - node[node[omg].fa].len;
printf("%lld\n",ans);
}
}
return 0;
}