http://www.elijahqi.win/archives/2990
Description
魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示。例如可以将魔咒字符 1、2 拼凑起来形成一个魔咒串 [1,2]。
一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒。
例如 S=[1,2,1] 时,它的生成魔咒有 [1]、[2]、[1,2]、[2,1]、[1,2,1] 五种。S=[1,1,1] 时,它的生成魔咒有 [1]、
[1,1]、[1,1,1] 三种。最初 S 为空串。共进行 n 次操作,每次操作是在 S 的结尾加入一个魔咒字符。每次操作后都
需要求出,当前的魔咒串 S 共有多少种生成魔咒。
Input
第一行一个整数 n。
第二行 n 个数,第 i 个数表示第 i 次操作加入的魔咒字符。
1≤n≤100000。,用来表示魔咒字符的数字 x 满足 1≤x≤10^9
Output
输出 n 行,每行一个数。第 i 行的数表示第 i 次操作后 S 的生成魔咒数量
Sample Input
7
1 2 3 3 3 1 2
Sample Output
1
3
6
9
12
17
22
HINT
Source
鸣谢Menci上传
每个节点对应若干个子串,所有节点代表的所有子串本质不同,节点i代表的子串个数为最长的长度减去par树上最长的长度
#include<map>
#include<cstdio>
#include<algorithm>
#define N 220000
#define ll long long
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=gc();}
while(ch<='9'&&ch>='0') x=(x<<3)+(x<<1)+ch-'0',ch=gc();
return x*f;
}
map<int,int> ch[N];ll ans;
int fa[N],last=1,cnt=1,root=1,len[N];
inline void insert1(int x){
int np=++cnt,p=last;fa[np]=p;len[np]=len[p]+1;
for (;p&&!ch[p][x];p=fa[p]) ch[p][x]=np;
if (!p) fa[np]=root;else{
int q=ch[p][x];if (len[p]+1==len[q]) fa[np]=q;else{
int nq=++cnt;ch[nq]=ch[q];fa[nq]=fa[q];fa[np]=fa[q]=nq;
len[nq]=len[p]+1;for (;p&&ch[p][x]==q;p=fa[p]) ch[p][x]=nq;
}
}last=np;ans+=len[np]-len[fa[np]];
}
int main(){
// freopen("bzoj4516.in","r",stdin);
for (register int i=read();i;--i) insert1(read()),printf("%lld\n",ans);
return 0;
}