后缀数组

后缀数组

今天被老师 强行
灌输后缀数组
然后就看了下
在代码中写的注释是我对sa的一点理解
大概就是每次排序,都与倍增出来的第二关键字,与上一次更新出的sa[]作为第一关键字相关
有错误欢迎指出 3Q

#include<cstdio>
#include<cstring>
#include<algorithm>
using std::swap;
const int maxn=2000010;

char c[maxn];
int s[maxn],sa[maxn];//后缀排名的位置
int rank[maxn];//后缀排名
int height[maxn];//常规操作
int saf[maxn];//用saf[]作为第2关键字后缀的第一关键字
int cs[maxn];//基数排序中的排名计数器
int n,m;
void rsort() {//第二关键字基数排序
    for(int i=0;i<=m;++i)cs[i]=0;
    for(int i=1;i<=n;++i)cs[rank[saf[i]]]++;
    for(int i=1;i<=m;++i)cs[i]+=cs[i-1];
    for(int i=n;i>=1;--i)sa[cs[rank[saf[i]]]--]=saf[i];//利用第二关键字排名更新sa
}
int cmp(int *f,int x,int y,int w) {
    return f[x]==f[y]&&f[x+w]==f[y+w];//cmp 
}
void get_sa() {
    for(int i=1;i<=n;++i)rank[i]=s[i],saf[i]=i;//此时saf[i]指向自己作为第一关键字的后缀
    m=127;rsort();
    for(int p=1,w=1,i;p<n;w<<=1,m=p) {//w为倍增长度,<选取第几位作为第二关键字>
        for(i=n-w+1,p=0;i<=n;++i)saf[++p]=i;
        for(i=1;i<=n;++i)if(sa[i]>w)saf[++p]=sa[i]-w;//利用上次的sa[]值更新下一次的saf[],有的字母已经不能再作为后缀的第n位的关键字了0
        rsort();swap(rank,saf);rank[sa[1]]=p=1;//p用来记录已经不需要再比较'第三关键字的'的后缀//当p=n是说明排序完成
        for(i=2;i<=n;++i)rank[sa[i]]=cmp(saf,sa[i],sa[i-1],w)?p:++p;//比较第一关键词与自己排名相临的,若第二关键字相同则需继续比较
    }
	//int j,k=0;
    //for(int i=1;i<=n;height[rank[i++]]=k)
      //  for(k=k?k-1:k,j=sa[rank[i]-1];s[i+k]==s[j+k];++k);
}
int main() {
    scanf("%s",c+1);
    n=strlen(c+1);
	for(int i=1;i<=n;++i)s[i]=c[i];
    s[0]=s[n+1]=-1;
    get_sa();
	for(int i=1;i<=n;++i) {
		printf("%d ",sa[i]);
	}
    return 0;
}

原文地址:https://www.cnblogs.com/sssy/p/8410902.html