您的位置:首页 > 其它

后缀数组详解

2017-05-18 15:19 393 查看
超赞后缀数讲解、代码尽在此处

https://zhuanlan.zhihu.com/p/21283102

http://blog.csdn.net/yxuanwkeith/article/details/50636898

记录一下自己学后缀数组看的博客

这两篇真心好

附上我的代码模板

#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<complex>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<set>
#include<map>

using namespace std;

typedef long long ll;

inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
inline void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}

const int N=100100;

int buc
,sa1
,sa2
,rk1
,rk2
,ht
;

int *sa=sa1,*tp=sa2,*rk=rk1,*tmp=rk2;

char s
;

int n,m;

void get_ht()
{
register int i,j,k=0;
for(i=1;i<n;++i)
{
j=rk[i]-1;
while(s[sa[rk[i]]+k]==s[sa[j]+k])k++;//
ht[rk[i]]=k;
if(k)k--;
}
}

void get_sa()
{
n=read();m=300;scanf("%s",s+1);
register int i,k,j;register bool flag(0);
for(i=1;i<=n;++i)buc[s[i]]++;
for(i=1;i<=m;++i)buc[i]+=buc[i-1];
for(i=n;i;--i)sa[buc[s[i]]--]=i;
for(i=1;i<=n;++i)rk[sa[i]]=rk[sa[i-1]]+(s[sa[i]]!=s[sa[i-1]]);

for(k=1;k<=n;k<<=1)
{
for(i=1;i<=n;++i)buc[rk[sa[i]]]=i;
for(i=n;i;--i)if(sa[i]>k)tp[buc[rk[sa[i]-k]]--]=sa[i]-k;
for(i=n-k+1;i<=n;++i)tp[buc[rk[i]]--]=i;
for(i=1;i<=n;++i)
{
tmp[tp[i]]=tmp[tp[i-1]]+(rk[tp[i]]!=rk[tp[i-1]]||rk[tp[i]+k]!=rk[tp[i-1]+k]);
if(tmp[tp[i]]==n)flag=1;
}
swap(tmp,rk);swap(sa,tp);
if(flag)break;
}
}

int main()
{
get_sa();get_ht();
register int i;
for(i=1;i<=n;++i)print(sa[i]-1),putchar(' ');puts("");
for(i=1;i<=n;++i)print(rk[i]),putchar(' ');puts("");
for(i=2;i<=n;++i)print(ht[i]),putchar(' ');puts("");
return 0;
}
/*
9
lixueling

4 8 6 1 5 0 7 3 2
6 4 9 8 1 5 3 7 2
0 0 1 0 2 0 0 0
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: