BZOJ 4516: [Sdoi2016]生成魔咒

裸的SAM。。。。。。。

考察點是啥?SAM的複雜度是O(n)而不是O(n*sigma)?

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<algorithm>
#include<map>
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
#define mmt(a,v) memset(a,v,sizeof(a))
#define tra(i,u) for(int i=head[u];i;i=e[i].next)
using namespace std;
typedef long long ll;
const int N=100000+5;
map<int,int>go[N<<1];
int par[N<<1],len[N<<1],sz,last,root;
ll ans;
int calc(int x){
	if(!par[x])return 0;
	return len[x]-len[par[x]];
}
void init(){root=last=++sz;}
void extend(int x){
	int p=last,np=++sz;
	len[np]=len[p]+1;
	for(;p&&!go[p].count(x);p=par[p])go[p][x]=np;
	if(!p)par[np]=root;
	else{
		int q=go[p][x];
		if(len[q]==len[p]+1)par[np]=q;
		else{
			int nq=++sz;
			len[nq]=len[p]+1;
			go[nq]=go[q];
			par[nq]=par[q];
			ans-=calc(q);
			par[q]=par[np]=nq;
			ans+=calc(q)+calc(nq);
			for(;p&&go[p][x]==q;p=par[p])go[p][x]=nq;
		}
	}
	ans+=calc(np);
	last=np;
}
int main(){
	//freopen("a.in","r",stdin);
	int n;scanf("%d",&n);
	init();
	rep(i,1,n){
		int x;scanf("%d",&x);
		extend(x);
		printf("%lld\n",ans);
	}
	return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章