传送门biu~
求本质不同的子串个数,相当于把SAM上的每一个节点表示的长度范围大小(Max-Min+1)求和。
#include<bits/stdc++.h>
using namespace std;
int n;long long ans;
struct Node{
map<int,Node*>ch;
Node* fa;
int val;
Node(int _=0){fa=NULL;val=_;}
}*root=new Node,*last=root;
inline void Insert(int x){
Node *p=last,*np=new Node(p->val+1);
last=np;
while(p && !p->ch[x]) p->ch[x]=np,p=p->fa;
if(!p){
np->fa=root;
ans+=np->val;
return;
}
Node *q=p->ch[x];
if(q->val==p->val+1){
np->fa=q;
ans+=np->val-q->val;
return;
}
Node *nq=new Node(p->val+1);
nq->fa=q->fa;
nq->ch=q->ch;
q->fa=np->fa=nq;
while(p && p->ch[x]==q) p->ch[x]=nq,p=p->fa;
ans+=np->val-np->fa->val;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
int x;
scanf("%d",&x);
Insert(x);
printf("%lld\n",ans);
}
return 0;
}