bzoj3899 弦论

好久没有更blog了啊。。。

对于一个给定长度为N的字符串,求它的第K小子串是什么。

这是一个SAM的模板题。

我好弱啊这个时候才开始学SAM,才会用指针。

要维护3个东西:每个状态right集合的大小、每个状态能到达的所有状态的right集合总大小、每个状态能到达的所有状态数

我没有判-1的情况反正没有-1的数据也能过

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const int maxn=5e5+10;
int n,k,o;
char s[maxn];

char cc;ll ff;
template<typename T>void read(T& aa) {
	aa=0;ff=1; cc=getchar();
	while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar();
	if(cc=='-') ff=-1,cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	aa*=ff;
}

struct Sam{
	Sam *next[27],*par;
	int step;ll right,sum[2];
}pool[2*maxn],*last,*root;
int tot;

Sam* newnode(int step) {
	Sam* t=pool+(tot++);
	memset(t->next,0,sizeof(t->next));
	t->par=NULL;
	t->step=step;
	t->right=t->sum[0]=t->sum[1]=0;
	return t; 
}

void Extend(int w) {
	Sam *p=last;
	Sam *np=newnode(p->step+1);np->right=1;
	for(;p&&!p->next[w];p=p->par) p->next[w]=np;
	if(!p) np->par=root;
	else {
		Sam *q=p->next[w];
		if(q->step==p->step+1) np->par=q;
		else {
			Sam *nq=newnode(p->step+1);
			memcpy(nq->next,q->next,sizeof(q->next));
			nq->par=q->par;
			q->par=nq; np->par=nq;
			for(;p&&p->next[w]==q;p=p->par) p->next[w]=nq;
		}
	}
	last=np;
}

int c[2*maxn];Sam *sa[2*maxn];
void get_jp() {
	Sam *r,*t;
	for(r=pool+1;r!=pool+tot;++r) c[r->step]++;
	for(int i=1;i<=n;++i) c[i]+=c[i-1];
	for(r=pool+1;r!=pool+tot;++r) sa[c[r->step]--]=r;
	for(int i=tot-1;i;--i) {
		r=sa[i]; 
		r->sum[0]=1;
		r->sum[1]=r->right;
		t=r->par;
		t->right+=r->right;
		for(int j=0;j<26;++j) {
			t=r->next[j];
			if(!t) continue;
			r->sum[0]+=t->sum[0];
			r->sum[1]+=t->sum[1];
		}
	}
}

void travel() {
	Sam *r=root,*t;
	while(k) {
		for(int i=0;i<26&&k;++i) {
			t=r->next[i];
			if(!t) continue;
			if(t->sum[o]>=k) {
				printf("%c",i+'a');
				break;
			}
			k-=t->sum[o];
		}
		r=t;
		if(o==1&&k<=r->right) break;
		if(o==0&&k<=1) break;
		k-= o==0? 1 : r->right;
	}
}

int main() {
	scanf("%s",s+1); n=strlen(s+1);
	last=root=newnode(0);
	for(int i=1;i<=n;++i) Extend(s[i]-'a');
	get_jp();
	read(o); read(k);
	travel();
	return 0;
}

  

顺便再放一道水题(spoj8222)的代码

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const int maxn=250000+7;
int n,ans[maxn];
char s[maxn]; 

char cc;ll ff;
template<typename T>void read(T& aa) {
	aa=0;ff=1; cc=getchar();
	while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar();
	if(cc=='-') ff=-1,cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	aa*=ff;
}

struct Sam{
	Sam *next[27],*par;
	int step,right;
}pool[2*maxn],*last,*root;
int tot;

Sam* newnode(int step) {
	Sam *t=pool+(tot++);
	memset(t->next,0,sizeof(t->next));
	t->step=step; t->right=0;
	return t;
}

void Extend(int w) {
	Sam *p=last;
	Sam *np=newnode(p->step+1); np->right=1;
	for(;p&&!p->next[w];p=p->par) p->next[w]=np;
	if(!p) np->par=root;
	else {
		Sam *q=p->next[w];
		if(q->step==p->step+1) np->par=q;
		else {
			Sam *nq=newnode(p->step+1);
			memcpy(nq->next,q->next,sizeof(q->next));
			nq->par=q->par;
			q->par=nq; np->par=nq;
			for(;p&&p->next[w]==q;p=p->par) p->next[w]=nq;
		}
	}
	last=np;
}

int c[2*maxn];Sam *sa[2*maxn];
void csort() {
	Sam *t;
	for(t=pool+1;t!=pool+tot;++t) c[t->step]++;
	for(int i=1;i<=n;++i) c[i]+=c[i-1];
	for(t=pool+1;t!=pool+tot;++t) sa[c[t->step]--]=t;
	for(int i=tot-1;i;--i) {
		t=sa[i];
		ans[t->step]=max(ans[t->step],t->right);
		t->par->right+=t->right;
	}
}

int main() {
	scanf("%s",s+1); last=root=newnode(0);
	n=strlen(s+1);
	for(int i=1;i<=n;++i) Extend(s[i]-'a');
	csort();
	for(int i=n;i;--i) ans[i]=max(ans[i],ans[i+1]);
	for(int i=1;i<=n;++i) printf("%d\n",ans[i]);
	return 0;
}

  

posted @ 2018-01-05 21:40  shixinyi  阅读(221)  评论(0编辑  收藏  举报