# 使用后缀自动机求后缀数组

#include <bits/stdc++.h>
using namespace std;

int last,dis[200001],val[200001],cnt,a[200001][26],fa[200001],sa[200001],n,sta[200001],top;
int tr[200001][26],rank[200001],height[200001];
char st[200001];

void ins(int num,int pos){
int p=last,np=last=++cnt;
dis[np]=dis[p]+1;val[np]=pos;
while (!a[p][num]&&p) a[p][num]=np,p=fa[p];
if (!p) fa[np]=1;else{
int q=a[p][num];
if (dis[p]+1==dis[q]) fa[np]=q;else{
int nq=++cnt;dis[nq]=dis[p]+1;
memcpy(a[nq],a[q],sizeof(a[q]));
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
while (a[p][num]==q) a[p][num]=nq,p=fa[p];
}
}
}

void dfs1(int po){
for (int i=0;i<26;i++)
if (a[po][i]&&dis[a[po][i]]==dis[po]+1){
sta[++top]=i;
tr[fa[a[po][i]]][sta[dis[a[po][i]]-dis[fa[a[po][i]]]]]=a[po][i];//确定后缀树的出边
dfs1(a[po][i]);
top--;
}
}

void dfs2(int po){
if (val[po]) sa[++cnt]=val[po];
for (int i=0;i<26;i++)
if (tr[po][i])
dfs2(tr[po][i]);
}

void getheight(){
int k=0;
int po1,po2;
for (int i=1;i<=n;i++){
po1=i,po2=sa[rank[i]-1];
if (k) k--;
while ((st[po1+k]==st[po2+k])&&(po1+k<=n)&&(po2+k<=n))
k++;
height[rank[i]-1]=k;
}
}

int main(){
scanf("%s",st+1);
n=strlen(st+1);
last=cnt=1;
for (int i=n;i>=1;i--)
ins(st[i]-'a',i);

dfs1(1);
cnt=0;
dfs2(1);
for (int i=1;i<=n;i++) rank[sa[i]]=i;
getheight();

for (int i=1;i<=n;i++) printf("%d ",sa[i]);printf("\n");
for (int i=1;i<n;i++) printf("%d ",height[i]);
}

posted @ 2017-12-07 15:43 z1j1n1 阅读(...) 评论(...) 编辑 收藏