bzoj3998: [TJOI2015]弦论

SAM小裸题qwq

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define N 1000006

using namespace std;
int OP;
struct SAM{
	int val[N],sum[N];
	#define u q[i]
	struct SAMnode{
		int par,mx,go[26];
	} t[N];
	int last,size;
	int newnode(int _mx){
		t[++size].par=0;t[size].mx=_mx;val[size]=0;
		memset(t[size].go,0,sizeof(t[size].go));
		return size;
	}
	void clear(){size=0;last=newnode(0);}
	void extend(char c){
		c-='a';
		int p=last,np=newnode(t[p].mx+1);
		for (;p&&!t[p].go[c];p=t[p].par) t[p].go[c]=np;
		if (!p) t[np].par=1;
		else{
			int q=t[p].go[c];
			if (t[p].mx+1==t[q].mx) t[np].par=q;
			else{
				int nq=newnode(t[p].mx+1);
				memcpy(t[nq].go,t[q].go,sizeof(t[q].go));
				t[nq].par=t[q].par;
				t[q].par=t[np].par=nq;
				for (;p&&t[p].go[c]==q;p=t[p].par) t[p].go[c]=nq;
			}
		}
		last=np;
		val[last]=1;
	}
	int v[N],q[N];
	void precompute(){
		memset(v,0,sizeof(v));
		for (int i=1;i<=size;++i) ++v[t[i].mx];
		for (int i=1;i<=size;++i) v[i]+=v[i-1];
		for (int i=size;i;--i) q[v[t[i].mx]--]=i;
		
		if (!OP) for (int i=1;i<=size;++i) val[i]=1;
		else for (int i=size;i;--i) val[t[u].par]+=val[u];
		val[1]=0;
		
		for (int i=size;i;--i){
			sum[u]=val[u];
			for (int j=0;j<26;++j)if (t[u].go[j])
				sum[u]+=sum[t[u].go[j]];
		} 
	}
	void solve(int p,int k){
		if ((k-=val[p])<=0) return;
		for (int i=0;i<26;++i)if (t[p].go[i]){
			if (sum[t[p].go[i]]>=k){
				putchar('a'+i);
				solve(t[p].go[i],k);
				return;
			}
			k-=sum[t[p].go[i]];
		}
		printf("-1");
	}
} sam;

char st[N];
int main(){
	scanf("%s",st);
	sam.clear();
	for (int i=0;st[i];++i) sam.extend(st[i]);
	int K;scanf("%d%d",&OP,&K);
	sam.precompute();
	sam.solve(1,K);puts("");
	return 0;
}

  

原文地址:https://www.cnblogs.com/wangyurzee7/p/5325463.html