2013-team5/Suffix-array
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
{{{
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
typedef long long LL;
const int MN=1e6+7;
int T[MN],sa[MN],tsa[MN],rank[MN*2],trank[MN],c[MN],height[MN];
void bsort(int k,int n){ /* 双关键字基数排序 */
int i;
memset(c,0,sizeof(c)); /* 以第二关键字基数排序 */
for (i=0; i<n; i++) c[rank[i+k]]++;
for (i=1; i<n; i++) c[i]+=c[i-1];
for (i=n-1; i>=0; i--) tsa[--c[rank[i+k]]]=i;
memset(c,0,sizeof(c)); /* 以第一关键字基数排序 */
for (i=0; i<n; i++) c[rank[i]]++;
for (i=1; i<n; i++) c[i]+=c[i-1];
for (i=n-1; i>=0; i--) sa[--c[rank[tsa[i]]]]=tsa[i];
/* 这样相当于,当第一关键字相同时,采用通过第二关键字排的顺序 */
}
void getsa(int *T,int *sa,int n){
int i,k,p;
memset(rank,0,sizeof(rank));
memset(c,0,sizeof(c));
for (i=0; i<n; i++) c[T[i]]++;
for (i=1; i<max(n,128); i++) c[i]+=c[i-1]; /* n可能小于字符种类数 */
for (i=n-1; i>=0; i--) sa[--c[T[i]]]=i;
rank[sa[0]]=p=1; /* Notice! */
for (i=1; i<n; i++) rank[sa[i]]=(T[sa[i]]==T[sa[i-1]])?p:++p;
for (k=1; k<=n && p<n; k<<=1){
bsort(k,n);
trank[sa[0]]=p=1;
for (i=1; i<n; i++)
trank[sa[i]]=(rank[sa[i-1]]==rank[sa[i]] && rank[sa[i-1]+k]==rank[sa[i]+k])?p:++p;
for (i=0; i<n; i++) rank[i]=trank[i];
}
}
void getheight(int* T,int* sa,int *height,int n){
int i,j,k;
for (i=0; i<n; i++) rank[sa[i]]=i;
k=0; height[0]=0;
for (i=0; i<n; i++){
if (k) k--;
if (rank[i]==0) continue;
int j=sa[rank[i]-1];
while (T[i+k]==T[j+k]) k++;
height[rank[i]]=k;
}
} /* height[i]表示sa[i-1]与sa[i]的最长公共前缀长度, 其中height[0]=0 */
}}}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
typedef long long LL;
const int MN=1e6+7;
int T[MN],sa[MN],tsa[MN],rank[MN*2],trank[MN],c[MN],height[MN];
void bsort(int k,int n){ /* 双关键字基数排序 */
int i;
memset(c,0,sizeof(c)); /* 以第二关键字基数排序 */
for (i=0; i<n; i++) c[rank[i+k]]++;
for (i=1; i<n; i++) c[i]+=c[i-1];
for (i=n-1; i>=0; i--) tsa[--c[rank[i+k]]]=i;
memset(c,0,sizeof(c)); /* 以第一关键字基数排序 */
for (i=0; i<n; i++) c[rank[i]]++;
for (i=1; i<n; i++) c[i]+=c[i-1];
for (i=n-1; i>=0; i--) sa[--c[rank[tsa[i]]]]=tsa[i];
/* 这样相当于,当第一关键字相同时,采用通过第二关键字排的顺序 */
}
void getsa(int *T,int *sa,int n){
int i,k,p;
memset(rank,0,sizeof(rank));
memset(c,0,sizeof(c));
for (i=0; i<n; i++) c[T[i]]++;
for (i=1; i<max(n,128); i++) c[i]+=c[i-1]; /* n可能小于字符种类数 */
for (i=n-1; i>=0; i--) sa[--c[T[i]]]=i;
rank[sa[0]]=p=1; /* Notice! */
for (i=1; i<n; i++) rank[sa[i]]=(T[sa[i]]==T[sa[i-1]])?p:++p;
for (k=1; k<=n && p<n; k<<=1){
bsort(k,n);
trank[sa[0]]=p=1;
for (i=1; i<n; i++)
trank[sa[i]]=(rank[sa[i-1]]==rank[sa[i]] && rank[sa[i-1]+k]==rank[sa[i]+k])?p:++p;
for (i=0; i<n; i++) rank[i]=trank[i];
}
}
void getheight(int* T,int* sa,int *height,int n){
int i,j,k;
for (i=0; i<n; i++) rank[sa[i]]=i;
k=0; height[0]=0;
for (i=0; i<n; i++){
if (k) k--;
if (rank[i]==0) continue;
int j=sa[rank[i]-1];
while (T[i+k]==T[j+k]) k++;
height[rank[i]]=k;
}
} /* height[i]表示sa[i-1]与sa[i]的最长公共前缀长度, 其中height[0]=0 */