您的位置:首页 > 其它

[BZOJ4516][SDOI2016]生成魔咒(后缀自动机)

2018-03-28 17:12 525 查看

4516: [Sdoi2016]生成魔咒

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1549  Solved: 899
[Submit][Status][Discuss]

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上传

[Submit][Status][Discuss]

SAM裸题?son数组用map存,实时统计mx[i]-mx[fa[i]]即可。

#include<map>
#include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
typedef long long ll;
using namespace std;

const int N=400100;
map<int,int>son
;
int cnt=1,lst=1,p,np,n,mx
,fa
,a
;
ll ans;

int F(int x){ return mx[x]-mx[fa[x]]; }

void ext(int c){
p=lst; np=lst=++cnt; mx[np]=mx

+1; while (p && !son[p][c]) son[p][c]=np,p=fa[p]; if (!p) fa[np]=1,ans+=F(np); else{ int q=son[p][c]; if (mx[q]==mx[p]+1) fa[np]=q,ans+=F(np); else{ int nq=++cnt; mx[nq]=mx[p]+1; son[nq]=son[q]; while (p && son[p][c]==q) son[p][c]=nq,p=fa[p]; fa[nq]=fa[q]; ans+=F(nq)-F(q); fa[q]=fa[np]=nq; ans+=F(np)+F(q); } } } int main(){ freopen("incantation.in","r",stdin); freopen("incantation.out","w",stdout); scanf("%d",&n); rep(i,1,n) scanf("%d",&a[i]),ext(a[i]),printf("%lld\n",ans); return 0; }

[p] 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: