P4070 [SDOI2016]生成魔咒
题目
有点水
做法
每次把加上\(np\)这个点新生产的串,直接加上\(np.longest-np.fail.longest\)
My complete code
#include<map>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
typedef long long LL;
const LL maxn=1000000;
inline LL Read(){
LL x(0),f(1);char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
return x*f;
}
LL n,nod=1,lst=1,sum;
LL a[maxn];
struct SAM{
LL fail,len;
map<LL,LL> son;
}S[maxn];
inline void Insert(LL c){
LL np=++nod,p=lst; lst=nod;
S[np].len=S[p].len+1;
while(p&&S[p].son[c]==0){
S[p].son[c]=np;
p=S[p].fail;
}
if(!p)
S[np].fail=1;
else{
LL q=S[p].son[c];
if(S[q].len==S[p].len+1)
S[np].fail=q;
else{
LL nq=++nod; S[nq].len=S[p].len+1;
S[nq].son=S[q].son;
S[nq].fail=S[q].fail;
//sum+=S[nq].len-S[S[nq].fail].len;
S[q].fail=S[np].fail=nq;
while(p&&S[p].son[c]==q){
S[p].son[c]=nq;
p=S[p].fail;
}
}
}
}
int main(){
n=Read();
for(LL i=1;i<=n;++i){
a[i]=Read();
Insert(a[i]);
sum+=S[lst].len-S[S[lst].fail].len;
printf("%lld\n",sum);
}
return 0;
}