1. 程式人生 > 實用技巧 >2020牛客多校第一場 B-Suffix Array (字尾陣列)

2020牛客多校第一場 B-Suffix Array (字尾陣列)

題目連結:傳送門

題目思路:傳送門

     排序時,以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?'\n':' '); for(int i=1;i<=n;i++) c[i]=x[i]=y[i]=0; } return 0; } /* 10 abbaababaa */
View Code