前天在看后缀数组相关的内容时,看了罗穗骞的论文,看了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
* */
本文详细解析了后缀数组2倍增法的实现原理,并通过一个示例程序来展示具体的步骤。作者分享了自己对罗穗骞论文的学习心得,特别是针对2倍增法的理解过程。文中提供了完整的C++代码示例,包括后缀数组的构建、高度数组的计算等关键部分。
473

被折叠的 条评论
为什么被折叠?



