您的位置:首页 > 其它

后缀数组

2012-10-21 15:46 447 查看
   几天下来终于大体明白了后缀数组的这一算法,真是不易 啊,就看那一个个for循环吧,就够晕的,其中要明白那个排序算法很关键,求height[ ]的更是经典 推荐看这个算法的网址是:  www.nocow.cn/index.php/%E5%90%8E%E7%BC%80%E6%95%B0%E7%BB%84,体会一下那个算法,下面这个程序,是自己理解后写出的对输入的字符串求 后缀排名 和最长公共前缀的算法(没经过测试)

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
int sa[100000],tsa[100000];
int rank[100000],tank[100000];
int height[100000];
int maxlen=10000;
char s1[100000];
int l;
int main()
{
void get_rank();
void get_height();
int i,j,n,m,s,t;
while(scanf("%s",s1)!=EOF)
{
l=strlen(s1);
get_rank();
get_height();
for(i=1;i<=l;i++)
{
cout<<s1+sa[i]-1<<endl;
}
for(i=1;i<=l;i++)
{
cout<<height[i]<<endl;
}
}
return 0;
}
void sort(int j)
{
int sum[100000];
int i;
memset(sum,0,sizeof(sum));
for(i=1;i<=l;i++)
{
sum[rank[i+j]]+=1;
}
for(i=1;i<=maxlen;i++)
{
sum[i]+=sum[i-1];
}
for(i=l;i>=1;i--)
{
tsa[sum[rank[i+j]]--]=i;
}
memset(sum,0,sizeof(sum));
for(i=1;i<=l;i++)
{
sum[rank[i]]++;
}
for(i=1;i<=maxlen;i++)
{
sum[i]+=sum[i-1];
}
for(i=l;i>=1;i--)
{
sa[sum[rank[tsa[i]]]--]=tsa[i];
}
}
void get_rank()
{
int sum[100000];
int i,j;
memset(sum,0,sizeof(sum));
memset(rank,0,sizeof(rank));
for(i=0;i<=l-1;i++)
{
tank[i+1]=s1[i];
}
for(i=1;i<=l;i++)
{
sum[tank[i]]+=1;
}
for(i=1;i<=maxlen;i++)
{
sum[i]+=sum[i-1];
}
for(i=l;i>=1;i--)
{
sa[sum[tank[i]]--]=i;
}
int p=1;
rank[sa[1]]=1;
for(i=2;i<=l;i++)
{
if(tank[sa[i-1]]!=tank[sa[i]])
{
p++;
}
rank[sa[i]]=p;
}
for(j=1;j<=l;j*=2)
{
sort(j);
tank[sa[1]]=1; p=1;
for(i=2;i<=l;i++)
{
if(rank[sa[i-1]]!=rank[sa[i]]||rank[sa[i-1]+j]!=rank[sa[i]+j])
{
p++;
}
tank[sa[i]]=p;
}
for(i=1;i<=l;i++)
{
rank[i]=tank[i];
}
}
}
void get_height()
{
int i,j;
j=0;
memset(height,0,sizeof(height));
for(i=1;i<=l;i++)
{
if(rank[i]==1)
{
height[rank[i]]=-1;
continue;
}
for(;s1[i+j-1]==s1[sa[rank[i]-1]+j-1];)
{
j++;
}
height[rank[i]]=j;
if(j)
{
j--;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 测试