后缀自动机入门题
因为后缀自动机上无相同字符串,所以每次添加一个字符之后增加的本质不同的字符串的个数就是len[x]-len[fa[x]]
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
using namespace std;
const int maxn=2e5+10;
int n,x;
long long ans;
struct suda
{
struct da{map<int,int>ch; int fa,len;}po[maxn];
int las,tot;
void init()
{
for (int i=1;i<=2*n;i++)
{
po[i].ch.clear();
po[i].fa=po[i].len=0;
}
las=tot=1;
}
void insert(int x)
{
int p=las,np=las=++tot; po[np].len=po[p].len+1;
for (;p&&(!po[p].ch.count(x));p=po[p].fa) po[p].ch[x]=np;
if (!p)
{
po[np].fa=1;
ans+=po[np].len-po[1].len;
}
else
{
int q=po[p].ch[x];
if (po[q].len==po[p].len+1)
{
po[np].fa=q;
ans+=po[np].len-po[q].len;
}
else
{
int nq=++tot; po[nq]=po[q];
po[nq].len=po[p].len+1;
po[q].fa=po[np].fa=nq;
ans+=po[np].len-po[nq].len;
for (;p&&(po[p].ch[x]==q);p=po[p].fa) po[p].ch[x]=nq;
}
}
}
}SAM;
int main()
{
scanf("%d",&n); SAM.init();
for (int i=1;i<=n;i++)
{
scanf("%d",&x);
SAM.insert(x);
printf("%lld\n",ans);
}
return 0;
}