首页 > 【刷题】BZOJ 4516 [Sdoi2016]生成魔咒

【刷题】BZOJ 4516 [Sdoi2016]生成魔咒

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

Solution

SAM模板题

每次加入新字符,对答案造成的贡献是 (len[x]-len[fa[x]]) ,因为以新字符为结尾,开头可以有 (len[x]-len[fa[x]]) 种情况

然后字符集的范围是真的无聊,于是就上了pbds的hash_table

#include
#include
#include
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
using namespace __gnu_pbds;
const int MAXN=100000+10;
int las=1,tot=1,len[MAXN<<1],fa[MAXN<<1],n;
ll ans;
cc_hash_table ch[MAXN<<1];
template inline void read(T &x)
{T data=0,w=1;char ch=0;while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();if(ch=='-')w=-1,ch=getchar();while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();x=data*w;
}
template inline void write(T x,char ch='')
{if(x<0)putchar('-'),x=-x;if(x>9)write(x/10);putchar(x%10+'0');if(ch!='')putchar(ch);
}
template inline void chkmin(T &x,T y){x=(y inline void chkmax(T &x,T y){x=(y>x?y:x);}
template inline T min(T x,T y){return x inline T max(T x,T y){return x>y?x:y;}
inline ll extend(int c)
{int p=las,np=++tot;las=np;len[np]=len[p]+1;while(p&&!ch[p][c])ch[p][c]=np,p=fa[p];if(!p)fa[np]=1;else{int q=ch[p][c];if(len[q]==len[p]+1)fa[np]=q;else{int nq=++tot;fa[nq]=fa[q];ch[nq]=ch[q];len[nq]=len[p]+1,fa[q]=fa[np]=nq;while(p&&ch[p][c]==q)ch[p][c]=nq,p=fa[p];}}return len[np]-len[fa[np]];
}
int main()
{read(n);for(register int i=1,x;i<=n;++i){read(x);ans+=extend(x);write(ans,'
');}return 0;
}

转载于:https://www.cnblogs.com/hongyj/p/9102276.html

更多相关:

  • $dp$。 这道题最关键的是这句话: 跳出思维局限大胆设状态,设$f_{x, i, j}$表示从$x$到根要经过$i$条公路,$j$条铁路的代价,那么对于一个叶子结点,有$f_{x, i, j} = c_x * (a_x + i) * (b_x + j)$,对于内部结点,有转移:   $f_{x, i, j} = min(f_{lso...

  • 合作者:201631062327,201631062128码云地址:https://gitee.com/LIUJIA6/WordCount3 一:项目说明 本次项目是在上次作业WorldCount的基础上,利用结对编程的思想,完成对WorldCount项目的功能扩展 -s 递归处理目录下符合条件的文件。(实现)-a 返回更复杂的数据(...

  •   【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=5972   【题目大意】   给出一个字符串,找出其中所有的符合特定模式的子串位置,符合特定模式是指,该子串的长度为n,并且第i个字符需要在给定的字符集合Si中    【题解】   利用ShiftAnd匹配算法。   bt[i]表示...

  • 首先我们可以发现如果错过了一个加油站,而继续往前走的时候没有油了,可以再假装之前经过加油站的时候加过油 于是我们维护一个大根堆,表示错过的加油站是哪些,每当没有油的时候从堆顶取出最大值加上去即可   1 /**************************************************************...

  • 嗯~ o(* ̄▽ ̄*)o lca是树上两点的最近公共祖先。如果在同一个分支上就是更靠近根的那个点,否则就是大家一起向上走,第一次能都经过的那个点。 根据这两个性质,我们对于每次询问可以把一个向上走到根节点,标记走过的点。然后从另一个点向上走,直到遇到第一个标记过的点即为lca。 如果整个树是一个长链,这样的方法就会退化成一复杂度为n...

  • 折腾了好久。不过收获还是很多的。第一次自己去画SAM所建出来fail树。深入体会了这棵树的神奇性质。 当然,我最终靠着自己A掉了。(这是我第一次推SAM的性质(以前都是抄别人的,感觉自己好可耻),不过感觉好像是摸着黑行走啊!) 这道题,可以先对第一个串建出后缀自动机。然后第二个串在后缀自动机上跑。 首先,SAM所建出的fail树的性质...