1. 程式人生 > 其它 >acwing 140. 字尾陣列

acwing 140. 字尾陣列

把字串S的所有後綴按照字典序排列,排名為 i 的字尾記為SA[ i ]

額外地,我們考慮排名為 i 的字尾與排名為  i-1 的字尾,把二者的最長公共字首的長度記為 hgt[i]

使用快排、Hash 與二分 求出 兩個陣列

#include<iostream>
#include <algorithm>
#include <cstring>
using namespace std;
 #define ll unsigned long long
  const int N=1e6+5;
  
 char s[N];
 int id[N],n;
 ll h[N],pow[N];
 ll bas
=131; ll f1(int l,int r){ return h[r]-h[l-1]*pow[r-l+1]; } int find(int a,int b){ int l=0,r=n-max(a,b)+1; int t=0; while(l<=r){ int md=(l+r)/2; if(f1(a,a+md-1)==f1(b,b+md-1)) l=md+1,t=md; else r=md-1; } return
t; } int cmp(int i,int j){ int k=find(i,j); int t1,t2; if(i+k<=n) t1=s[i+k]; else t1=-1e9; if(j+k<=n) t2=s[j+k]; else t2=-1e9; return t1<t2; } void sov(){ h[0]=0; int i,ans=0; n=strlen(s+1); for(i=1;i<=n;i++){ h[i]=h[i-1]*bas+s[i]; id[i]
=i; } sort(id+1,id+1+n,cmp); for(i=1;i<=n;i++) cout<<id[i]-1<<' '; cout<<endl<<0; for(i=2;i<=n;i++) cout<<' '<<find(id[i],id[i-1]); cout<<endl; } main(){ int i; pow[0]=1; for(i=1;i<=1e6;i++) pow[i]=pow[i-1]*bas; cin>>s+1; sov(); }