BZOJ 4516: [Sdoi2016]生成魔咒

Posted 北屿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 4516: [Sdoi2016]生成魔咒相关的知识,希望对你有一定的参考价值。

Description

给出一串数字,求每次插入一个数字后本质不同的子串.

Sol

SAM.

在 SAM 上添加节点的时候统计一下 \(val[np]-val[par[np]]\) 就可以了...

用 map 存一下边,复杂度 \(O(nlogn)\)

Code

/**************************************************************
    Problem: 4516
    User: BeiYu
    Language: C++
    Result: Accepted
    Time:812 ms
    Memory:14940 kb
****************************************************************/
 
#include<cstdio>
#include<cstring>
#include<map>
#include<iostream>
using namespace std;
 
typedef long long LL;
const int N = 200005;
 
int n,cnt,rt,lst;
LL ans;
map<int,int> go[N];
int par[N],val[N];
 
inline int in(int x=0,char ch=getchar()){ while(ch>‘9‘||ch<‘0‘) ch=getchar();
    while(ch>=‘0‘&&ch<=‘9‘) x=(x<<3)+(x<<1)+ch-‘0‘,ch=getchar();return x; }
 
void Extend(int w=in()){
    int p=lst,np=++cnt;
    val[np]=val[p]+1;
    while(p && go[p][w]==0) go[p][w]=np,p=par[p];
    if(!p) par[np]=rt;
    else{
        int q=go[p][w];
        if(val[p]+1 == val[q]) par[np]=q;
        else{
            int nq=++cnt;
            val[nq]=val[p]+1,go[nq]=go[q],par[nq]=par[q];
            par[q]=par[np]=nq;
            while(p && go[p][w]==q) go[p][w]=nq,p=par[p];
        }
    }ans+=val[np]-val[par[np]],lst=np;
}
 
int main(){
    lst=rt=++cnt,n=in();
    for(int i=1;i<=n;i++) Extend(),printf("%lld\n",ans);
    return 0;
}

  

以上是关于BZOJ 4516: [Sdoi2016]生成魔咒的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 4516: [Sdoi2016]生成魔咒

bzoj4516 [Sdoi2016]生成魔咒

BZOJ4516SDOI2016生成魔咒 [SAM]

BZOJ - 4516: [Sdoi2016]生成魔咒

BZOJ 4516: [Sdoi2016]生成魔咒

bzoj4516: [Sdoi2016]生成魔咒(SAM)