前天在看后缀数组相关的内容时,看了罗穗骞的论文,看了2天才基本看懂了论文中的2倍增法。但是还是没有理解完全。现在先做一个笔记,以便以后参考。(说实话,我觉得trie, p - trie什么的都没这么伤脑筋),以下是我在网上down的一个示例程序。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int cmp(int *r,int a,int b,int l){
return r[a]==r[b]&&r[a+l]==r[b+l];
}
//为什么设置为100结果就不正确呢
#define M 200
int wa[M],wb[M],wv[M],ws[M];
int SA[M];
char s[M]="aabaaaab";
void print(char *label,int *arr,int n){
puts(label);
for(int i=0;i<n;i++)
printf("%d ",arr[i]);
puts("");
}
void da(char *r,int *sa,int n,int m){
int i, j, p, *x = wa, *y = wb;
for (i = 0; i < m; i++)
ws[i] = 0;
for (i = 0; i < n; i++)
ws[x[i] = r[i]]++;
for (i = 1; i < m; i++)
ws[i] += ws[i - 1];
for (i = n - 1; i >= 0; i--)
sa[--ws[x[i]]] = i;
print("array sa:",sa,n); //**************print**************
for (j = 1, p = 1; p < n; j *= 2,m=p)
{
//对第二关键字进行排序:由上一次的结果 直接算出来
for (p = 0, i = n - j; i < n; i++) y[p++] = i;
for (i = 0; i < n; i++)
if (sa[i] >= j) y[p++] = sa[i] - j;
print("array y:",y,n);
print("array x:",x,n);
//对第一关键字进行排序
for (i = 0; i < n; i++) wv[i] = x[y[i]]; //根据第二关键字的顺序将后缀数组进行排序以便用于第一关键字的排序,注意论文中的图xy,
//先进行y排序,然后进行x排序。注意看论文中的图2,每次都是先根据上一次的结果算出第二个关键字的顺序放在y中,然后y的排序结果
//对第一个关键字即图中的x进行排序。
print("wv:",wv,n);//**************************************
for (i = 0; i < m; i++) ws[i] = 0;
for (i = 0; i < n; i++) ws[wv[i]]++;
for (i = 1; i < m; i++) ws[i] += ws[i - 1];
for (i = n - 1; i >= 0; i--) sa[--ws[ wv[i]]] = y[i];
print("sa:",SA,n+1);//**************print**************
for ( p = 1, y[sa[0]] = 0, i = 1; i < n; i++)
y[sa[i]] = cmp(x, sa[i - 1], sa[i], j) ? p - 1 : p++;
print("array y:",y,n);
print("array x:",x,n);
swap(x, y);
printf("----------------------------------------\n");
}
}
#define maxn 100
int rank[maxn],height[maxn];
void calheight(char*r,int*sa,int n)
{
int i,j,k=0;
for(i=1;i<=n;i++)rank[sa[i]]=i;
for(i=0;i<n;height[rank[i++]]=k)
for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
return;
}
int main(){
int n=strlen(s);
printf("n = %d\n",n);
int m=128;
da(s,SA,n + 1,m);
print("sa:",SA,n + 1);//**************print**************
for (int i = 0; i <= n; ++i)
{
printf("%s\n",&s[SA[i]]);
}
calheight(s,SA,n + 1);
print("height:",height,n + 1);
return 0;
}
/*
* sa:
8 3 4 5 0 6 1 7 2
* */