写一发后缀数组套路题,看起来简单,写起来要人命哦~~~
总共13题。
分两天debug吧,有点累了~~~
suffix(后缀数组的应用)
-
sa[i] :排名第 i 的后缀在哪(i 从 1 开始)
-
rank[i]:后缀 i 排第几 (i 从 0 开始)
-
height[i]:排名为 i 和 i-1 的两个后缀的最长公共前缀(LCP)长度 (i 从 2 开始)
模板:加上RMQ操作
#include <stdio.h> #include <string.h> #include <math.h> #include <algorithm> using namespace std; const int maxn = 2000000+5; int wa[maxn],wb[maxn],wv[maxn],ws[maxn]; int sa[maxn]; int r[maxn]; int cmp(int *r,int a,int b,int l) { return r[a]==r[b]&&r[a+l]==r[b+l]; } void da(int *r,int *sa,int n,int m) { int i,j,p,*x=wa,*y=wb,*t; for(i=0; i<m; i++) ws[i]=0; for(i=0; i<n; i++) ws[x[i]=r[i]]++; for(i=1; i<m; i++) ws[i]+=ws[i-1]; for(i=n-1; i>=0; i--) sa[--ws[x[i]]]=i; for(j=1,p=1; p<n; j*=2,m=p) { for(p=0,i=n-j; i<n; i++) y[p++]=i; for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i=0; i<n; i++) wv[i]=x[y[i]]; for(i=0; i<m; i++) ws[i]=0; for(i=0; i<n; i++) ws[wv[i]]++; for(i=1; i<m; i++) ws[i]+=ws[i-1]; for(i=n-1; i>=0; i--) sa[--ws[wv[i]]]=y[i]; for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; } return; } int ranks[maxn],height[maxn]; void calheight(int *r,int *sa,int n) { int i,j,k=0; for(i=1; i<=n; i++) ranks[sa[i]]=i; for(i=0; i<n; height[ranks[i++]]=k) for(k?k--:0,j=sa[ranks[i]-1]; r[i+k]==r[j+k]; k++); return; } char str[maxn]; int f[maxn][20]; void init(int len) { for(int i = 1; i <= len; i++) f[i][0] = height[i]; for(int s = 1; (1<<s)<=len; s++) { int tmp = (1<<s); for(int i = 1; i+tmp-1<=len; i++) { f[i][s] = min(f[i][s-1],f[i+tmp/2][s-1]); } } } int cal(int l,int r) { int len = log2(r-l+1); int ans = min(f[l][len],f[r-(1<<len)+1][len]); return ans; } int main() { freopen("in.txt","r",stdin); scanf("%s",str); int n = strlen(str); for(int i = 0; i < n; i++) r[i] = str[i] - 'a' + 1; da(r,sa,n+1,300); calheight(r,sa,n); for(int i = 1; i <= n; i++) { printf("%d ",sa[i]); } puts(""); for(int i = 0; i < n; i++) { printf("%d ",ranks[i]); } puts(""); for(int i = 2; i <= n; i++) { printf("%d ",height[i]); } puts(""); init(n); //height 上的 RMQ(); 从 2开始; printf("%d\n",cal(2,3)); return 0; }