花了点时间搞定了下后缀数组,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 100005 char 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; }