后缀自动机裸题,建的时候直接用max维护一下本质不同子串数量即可
置于为什么在新建nq节点的时候不需要更新ans,因为写一下会发现nq,q,fa[q]的mx都被加了一次又减了一次,抵消了
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<ctime>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<bitset>
#include<map>
using namespace std;
#define MAXN 200010
#define MAXM 10010
#define INF 1000000000
#define MOD 1000000007
#define ll long long
#define eps 1e-8
int fa[MAXN],dep[MAXN],mx[MAXN];
int rt,lst,tot;
map<int,int>son[MAXN];
int n;
ll ans;
void ins(int x){
int p=lst,np=++tot;
mx[np]=mx[p]+1;
while(p&&!son[p][x]){
son[p][x]=np;
p=fa[p];
}
if(!p){
fa[np]=rt;
}else{
int q=son[p][x];
if(mx[q]==mx[p]+1){
fa[np]=q;
}else{
int nq=++tot;
mx[nq]=mx[p]+1;
son[nq]=son[q];
fa[nq]=fa[q];
fa[np]=fa[q]=nq;
while(son[p][x]==q&&p){
son[p][x]=nq;
p=fa[p];
}
}
}
lst=np;
ans+=mx[np]-mx[fa[np]];
printf("%lld\n",ans);
}
int main(){
int i,x;
rt=tot=lst=1;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&x);
ins(x);
}
return 0;
}
/*
5
1 2 1 1 2
*/