【复习】后缀数组
贴模板,复习注意事项
补一句,SA是O(N(logN))的,暴力是O(N(log2(N)))的,不卡的话,实在忘记了,就暴力,实惠又划算
CODE:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=1e5+10; int sa[maxn],tmp[maxn],hei[maxn],x[maxn],y[maxn],c[maxn],f[maxn][21],bin[21]; char s[maxn]; inline void SA( int n, int m) { int p=0; 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>=1;i--) sa[c[x[i]]--]=i; //倒着 for ( int k=1;k<=n && p<=n;k<<=1) { p=0; for ( int i=n-k+1;i<=n;i++) y[++p]=i; //后面的不足k for ( int i=1;i<=n;i++) if (sa[i]>k) y[++p]=sa[i]-k; for ( int i=1;i<=m;i++) c[i]=0; for ( int i=1;i<=n;i++) c[x[y[i]]]++; for ( int i=1;i<=m;i++) c[i]+=c[i-1]; for ( int i=n;i>=1;i--) sa[c[x[y[i]]]--]=y[i]; //倒着 for ( int i=1;i<=n;i++) tmp[i]=x[i]; for ( int i=1;i<=n;i++) x[i]=y[i]; for ( int i=1;i<=n;i++) y[i]=tmp[i]; // swap(x,y); x[sa[1]]=p=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])?p:++p; m=p; } int k=0; for ( int i=1;i<=n;i++) { if (x[i]==1) continue ; if (k) k--; //>=hei[i-1]-1 int j=sa[x[i]-1]; //上一个排名 while (i+k<=n && j+k<=n && s[i+k]==s[j+k]) k++; hei[x[i]]=k; } } inline void pr( int l, int r) { for ( int i=l;i<=r;i++) printf ( "%c" ,s[i]); printf ( "\n" ); } int main() { scanf ( "%s" ,s+1); int n= strlen (s+1); SA(n,1000); return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步