题目链接:传送门
题目思路:传送门
排序时,以A段长度l为第一关键字 ,以rk[i+l] 即 B段的rank 为第二关键字
但是依然不对,这里有一个非常精妙的处理;
对于A段来说,是0开头和0结尾,但是 aa ->01 , aaa->011 , a->0
对于 01(A段长度为2)显然 是小于001(长度为2) ,但是01的长度现在确实2? 因此为了维护A的整体性质(0开头,0结尾),我们对于01...1 这类的字符串在后面补一个0,这样的话 01[0](长度为3,方括号是补充的0)显然就小于001(长度为2),01[0] 的B段是不存在的,那么可以假定B段存在且rank 可以设为一个更小的值; 但是对于 abbaaab 来说 后缀ab -> 00 , 后缀 b -> 0[0] ,显然 0[0] < 00 因此可以设置rk[n+1]=0 , rk[n+2]=-1,这样的话就能解决这个情况。
#include<bits/stdc++.h> #include<cstdio> #include<cstring> #include<ctype.h> #include<functional> #include<algorithm> #pragma GCC optimize(2) using namespace std; std::mt19937 rnd(233); typedef long long LL; typedef pair<int,int> pii; typedef pair<LL,LL> pLL; #define pb push_back #define mk make_pair #define fi first #define se second #define ls (i<<1) #define rs (i<<1|1) #define mem(a,b) memset(a,b,sizeof(a)) const int N=1e6+5; const int inf=0x3f3f3f3f; const LL mod=1e9+7; LL read() { LL x=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); } return f*x; } int sa[N],rk[N],x[N],y[N],c[N],he[N],n,m; struct node { int l,r,id; }a[N]; bool cmp(node p,node q) { return p.l==q.l?p.r<q.r:p.l<q.l; } char t[N]; int s[N]; void SA() { m=n; for(int i=1;i<=m;i++) c[i]=0; for(int i=1;i<=n;i++) c[x[i]=s[i]]++; for(int i=1;i<=m;i++) c[i]+=c[i-1]; for(int i=n;i;i--) sa[c[x[i]]--]=i; for(int k=1;k<=n;k<<=1) { int tot=0; for(int i=n-k+1;i<=n;i++) y[++tot]=i; for(int i=1;i<=n;i++) if(sa[i]>k) y[++tot]=sa[i]-k; for(int i=1;i<=m;i++) c[i]=0; for(int i=1;i<=n;i++) c[x[i]]++; for(int i=1;i<=m;i++) c[i]+=c[i-1]; for(int i=n;i;i--) sa[c[x[y[i]]]--]=y[i]; for(int i=1;i<=n;i++) y[i]=x[i]; x[sa[1]]=tot=1; for(int i=2;i<=n;i++) x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?tot:++tot); if(tot==n) break; m=tot; } for(int i=1;i<=n;i++) rk[sa[i]]=i; } int main() { while(scanf("%d",&n)!=EOF) { scanf("%s",t+1); int pa=0,pb=0; for(int i=1;i<=n;i++) { if(t[i]=='a') { if(pa) s[i]=i-pa+1; else s[i]=1; pa=i; } else { if(pb) s[i]=i-pb+1; else s[i]=1; pb=i; } } SA(); pa=pb=0; rk[n+1]=0,rk[n+2]=-1; for(int i=n;i;i--) { if(t[i]=='a') pa=i; else pb=i; if(!pa||!pb) { a[i].l=n-i+2; } else a[i].l=abs(pa-pb)+1; a[i].id=i; a[i].r=rk[i+a[i].l]; } sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++) printf("%d%c",a[i].id,i==n?' ':' '); for(int i=1;i<=n;i++) c[i]=x[i]=y[i]=0; } return 0; } /* 10 abbaababaa */