首页 > 代码库 > BZOJ 4516: [Sdoi2016]生成魔咒
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]生成魔咒
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。