求不同子串个数
裸的后缀自动机
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstdio> #define ll long long
#define N 2000007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-;ch=getchar();}
while(isdigit(ch)){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
} int n;
ll ans;
struct sam
{
int last,cnt;
int c[N][],fa[N],mx[N];
sam(){last=cnt=;}
void extend(int x)
{
int p=last,np=last=++cnt;mx[np]=mx[p]+;
while(p&&!c[p][x])
{
c[p][x]=np;
p=fa[p];
}
if(!p)fa[np]=;
else
{
int q=c[p][x];
if(mx[q]==mx[p]+)fa[np]=q;
else
{
int nq=++cnt;mx[nq]=mx[p]+;
memcpy(c[nq],c[q],sizeof(c[q]));
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
while(c[p][x]==q)c[p][x]=nq,p=fa[p];
}
}
}
}sam;
char s[N]; int main()
{
scanf("%s",s+);n=strlen(s+);
for (int i=;i<=n;i++)
sam.extend(s[i]-'a');
for (int i=;i<=sam.cnt;i++)
ans+=sam.mx[i]-sam.mx[sam.fa[i]];
printf("%lld",ans);
}