【uoj35】 后缀排序

http://uoj.ac/problem/35 (题目链接)

题意

  如题,并且求height数组。

Solution

  挂一发后缀自动机构后缀数组及height数组

细节

  注意基数排序和连边的时候不要把根节点也算进去

代码

// uoj35
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define LL long long
#define inf 2147483640
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;

const int maxn=100010;
int sa[maxn],height[maxn];
char s[maxn];

namespace SAM {
	int par[maxn<<1],len[maxn<<1],r[maxn<<1],ch[maxn<<1][26],pos[maxn<<1];
	int last,sz,Dargen,n,cnt;
	int b[maxn],id[maxn<<1],head[maxn<<1];
	
	struct edge {int to,next;}e[maxn<<2];
	
	void link(int u,int v) {
		e[++cnt]=(edge){v,head[u]};head[u]=cnt;
	}
	void Extend(int c) {
		int np=++sz,p=last;last=np;
		pos[np]=len[np]=r[np]=len[p]+1;
		for (;p && !ch[p][c];p=par[p]) ch[p][c]=np;
		if (!p) par[np]=Dargen;
		else {
			int q=ch[p][c];
			if (len[p]+1==len[q]) par[np]=q;
			else {
				int nq=++sz;
				len[nq]=len[p]+1;r[nq]=r[q];
				memcpy(ch[nq],ch[q],sizeof(ch[q]));
				par[nq]=par[q];
				par[np]=par[q]=nq;
				for (;p && ch[p][c]==q;p=par[p]) ch[p][c]=nq;
			}
		}
	}
	void build() {
		last=sz=Dargen=1;
		n=strlen(s+1);
		for (int i=1;i<=n>>1;i++) swap(s[i],s[n-i+1]);
		for (int i=1;i<=n;i++) Extend(s[i]-'a');
	}
	void dfs(int x,int l) {
		if (pos[x]) sa[++sz]=n-pos[x]+1,height[sz]=l;
		for (int i=head[x];i;i=e[i].next) {
			if (i==head[x]) dfs(e[i].to,pos[x] ? len[x] : l);
			else dfs(e[i].to,len[x]);
		}
	}
	void pre() {
		for (int i=1;i<=sz;i++) b[s[r[i]-len[par[i]]]-'a']++;
		for (int i=1;i<=26;i++) b[i]+=b[i-1];
		for (int i=2;i<=sz;i++) id[b[s[r[i]-len[par[i]]]-'a']--]=i;
		for (int i=sz-1;i>=1;i--) link(par[id[i]],id[i]);
		sz=0;dfs(1,0);
	}
}
using namespace SAM;
	
int main() {
	scanf("%s",s+1);
	build();
	pre();
	for (int i=1;i<=n;i++) printf("%d ",sa[i]);
	puts("");
	for (int i=2;i<=n;i++) printf("%d ",height[i]);
	return 0;
}

 

posted @ 2017-01-19 16:43  MashiroSky  阅读(224)  评论(0编辑  收藏  举报