用后缀数组求sa height数组
连学加调试搞了一天
注意字符范围
倍增停止时间
每个数组代表的意义!
#include <cstdio>
#include <cstring>
const int MAXN=100000*40+10;
char s[MAXN];
int len,tmp[MAXN],secsa[MAXN],rank[MAXN],sa[MAXN],height[MAXN],cnt[MAXN],init[MAXN];
int cc[MAXN],secondary[MAXN],n;
void get_sa()
{
for(int i=1;i<=len;i++) cnt[init[i]]++;
for(int i=1;i<=26;i++) cnt[i]+=cnt[i-1];
for(int i=len;i>=1;i--) sa[cnt[init[i]]--]=i;
rank[sa[1]]=1;int nn=1;
for(int i=2;i<=len;i++)
{
if(init[sa[i]]!=init[sa[i-1]]) nn++;
rank[sa[i]]=nn;
}
//printf("%d\n",nn);
for(int k=1;k<=len&&nn<len;k<<=1)
{
// for(int i=0;i<=26;i++) printf("%d ",cnt[i]);printf("\n");
for(int i=0;i<=len;i++) cnt[i]=0;
for(int i=1;i<=len;i++) cnt[rank[i+k]]++;
for(int i=1;i<=nn;i++) cnt[i]+=cnt[i-1];
//printf("%d\n",cnt[rank[99626+k]]);
for(int i=1;i<=len;i++) secsa[cnt[rank[i+k]]--]=i; // for(int i=1;i<=len;i++) printf("%d ",secsa[i]);printf("\n");
//for(int i=1;i<=len+k;i++) printf("%d ",rank[i]);printf("\n");
for(int i=0;i<=len;i++) cnt[i]=0;
for(int i=1;i<=len;i++) cnt[rank[i]]++;
for(int i=1;i<=nn;i++) cnt[i]+=cnt[i-1];
for(int i=len;i>=1;i--) sa[cnt[rank[secsa[i]]]--]=secsa[i];
nn=1;
tmp[sa[1]]=1;
for(int i=2;i<=len;i++)
{
if(rank[sa[i]]!=rank[sa[i-1]]||rank[sa[i]+k]!=rank[sa[i-1]+k]) nn++;
tmp[sa[i]]=nn;
}
for(int i=1;i<=len;i++) rank[i]=tmp[i];
// printf("%d %d\n",k,nn);
//for(int i=1;i<=len;i++) rank[i]=cnt[init[i]-1]+1;
// for(int i=1;i<=len;i++) printf("%d ",rank[i]);printf("\n");
}
int k=0;
for(int i=1;i<=len;i++)
{
if(k) k--;
int j=sa[rank[i]-1];
while(i+k<=len&&j+k<=len&&init[i+k]==init[j+k]) k++;
height[rank[i]]=k;
}
}
int main()
{
// freopen("a.in","r",stdin);
// freopen("wa.out","w",stdout);
scanf("%s",s+1);
len=strlen(s+1);n=len;
for(int i=1;i<=len;i++) init[i]=s[i]-'a'+1;
get_sa();
// suffix();
for(int i=1;i<=len;i++) printf("%d ",sa[i]);printf("\n");
for(int i=2;i<=len;i++) printf("%d ",height[i]);printf("\n");
return 0;
}