题解
后缀自动机板子题,直接统计 DAG 的路径数量即可,或者根据 (len) 数组的性质,即 (x) 节点产生的未出现的子串数量为 (len[x]-len[fa[x]])。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+10;
int n;
char s[N];
LL ans;
struct SuffixAutoMachine{
char *s;
int tot,last,ch[N*2][26],fa[N*2],len[N*2];
LL f[N*2];
int newnode(int id){tot++;memcpy(ch[tot],ch[id],sizeof(ch[tot]));fa[tot]=fa[id];len[tot]=len[id];return tot;}
void insert(int c){
int p=last,np=last=newnode(0);
len[np]=len[p]+1;
for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
if(!p) {fa[np]=1;return;}
int q=ch[p][c];
if(len[q]==len[p]+1) {fa[np]=q;return;}
int nq=newnode(q);len[nq]=len[p]+1;
fa[q]=fa[np]=nq;
for(;p&&ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
}
LL dfs(int u){
if(f[u]) return f[u];
for(int i=0;i<26;i++) if(ch[u][i]) f[u]+=dfs(ch[u][i])+1;
return f[u];
}
void init(char *_s){
memset(f,0,sizeof(f));
s=_s;last=newnode(0);
for(int i=1;i<=n;i++) insert(s[i]-'a');
ans=dfs(1);
}
}sam;
int main(){
scanf("%d",&n);
scanf("%s",s+1);
sam.init(s);
printf("%lld
",ans);
return 0;
}