后缀数组模板

来源:互联网 发布:oracle数据库试题 编辑:程序博客网 时间:2024/06/12 19:54

花了点时间搞定了下后缀数组,UOJ的例题,getSA有点厉害需要多思考下才行 算法合集——后缀数组

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<algorithm>#define LL long long#define fo(i,a,b) for(int i=a;i<=b;i++)#define down(i,a,b) for(int i=a;i>=b;i--)using namespace std;inline LL read(){LL d=0,f=1;char s=getchar();while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}return d*f;}#define N 100005char s[N];int a[N],rank[N],height[N];int n;bool com(int a,int b){int i=a,j=b;while(s[i]==s[j]){i++;j++;if(j>n)return 0;if(i>n)return 1;}if(s[i]<s[j])return 1;else return 0;}void getheight(){int i,j,k=0;for(i=1;i<=n;height[rank[i++]]=k)for(k?k--:0,j=a[rank[i]-1];s[i+k]==s[j+k];k++){//cout<<s[i+k]<<s[j+k]<<' '<<j<<' '<<k<<' '<<n<<endl;//cout<<i<<' '<<rank[i]<<' '<<a[rank[i-1]]<<endl;//if(i+k>n&&j+k>n)break;}fo(i,2,n)printf("%d ",height[i]);printf("\n");}void getsa(){fo(i,1,n)a[i]=i;sort(a+1,a+n+1,com);fo(i,1,n)rank[a[i]]=i;fo(i,1,n)printf("%d ",a[i]);printf("\n");}void getsaGG(){int c[N];int m=26;fo(i,1,m)c[i]=0;fo(i,1,n)rank[i]=s[i]-96,c[rank[i]]++;fo(i,1,m)c[i]+=c[i-1];down(i,n,1)a[c[rank[i]]--]=i;for(int k=1;k<=n;k<<=1){int p=0;fo(i,n-k+1,n)height[++p]=i;fo(i,1,n)if(a[i]>k)height[++p]=a[i]-k;fo(i,1,m)c[i]=0;fo(i,1,n)c[rank[height[i]]]++;fo(i,1,m)c[i]+=c[i-1];down(i,n,1)a[c[rank[height[i]]]--]=height[i];swap(rank,height);p=0;rank[a[1]]=++p;fo(i,2,n)if(height[a[i]]==height[a[i-1]]&&height[a[i]+k]==height[a[i-1]+k])rank[a[i]]=p;else rank[a[i]]=++p;if(p==n)break;m=p;}fo(i,1,n)printf("%d ",a[i]);printf("\n");}int main(){scanf("%s",s+1);n=strlen(s+1);getsaGG();getheight();//build_height();return 0;}


0 0
原创粉丝点击