orz……
后缀数组orz……
例如:n = 8;
num[] = { 1, 1, 2, 1, 1, 1, 1, 2, $ }; 注意 num 最后一位为 0,其他 大于 0
rank[] = 4, 6, 8, 1, 2, 3, 5, 7, 0 ;rank[0 n-1] 为有效值,rank[n] 必定为 0 无效值
sa[] = 8, 3, 4, 5, 0, 6, 1, 7, 2 ;sa[1 n] 为有效值,sa[0] 必定为 n 是 无效值
height[]= 0, 0, 3, 2, 3, 1, 2, 0, 1 ;height[2 n] 为有效值
const int maxn = 100010; int t1[maxn], t2[maxn], c[maxn]; bool cmp(int *r, int a, int b, int l) { return r[a] == r[b] && r[a+l] == r[b+l]; } void da(int str[], int sa[], int rank[], int height[], int n, int m) { n++; int p, *x = t1, *y = t2; for(int i = 0; i < m; i++) c[i] = 0; for(int i = 0; i < n; i++) c[x[i] = str[i]]++; for(int i = 1; i < m; i++) c[i] += c[i-1]; for(int i = n-1; i >= 0; i--) sa[--c[x[i]]] = i; for(int j = 1; j <= n; j <<= 1) { p = 0; for(int i = n-j; i < n; i++) y[p++] = i; for(int i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i] - j; for(int i = 0; i < m; i++) c[i] = 0; for(int i = 0; i < n; i++) c[x[y[i]]]++; for(int i = 1; i < m; i++) c[i] += c[i-1]; for(int i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i]; swap(x, y); p = 1, x[sa[0]] = 0; for(int i = 1; i < n; i++) x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p-1 : p++; if(p >= n) break; m = p; } int k = 0; n--; for(int i = 0; i <= n; i++) rank[sa[i]] = i; for(int i = 0; i < n; i++) { if(k) k--; int j = sa[rank[i]-1]; while(str[i+k] == str[j+k]) k++; height[rank[i]] = k; } } int rank[maxn], height[maxn], h[maxn]; int RMQ[maxn], mm[maxn]; int best[20][maxn]; void initRMQ(int n) { mm[0] = -1; for(int i = 1; i <= n; i++) mm[i] = ((i & (i-1)) == 0) ? mm[i-1]+1 : mm[i-1]; for(int i = 1; i <= n; i++) best[0][i] = i; for(int i = 1; i <= mm[n]; i++) for(int j = 1; j + (1<<i) - 1 <= n; j++) { int a = best[i-1][j]; int b = best[i-1][j + (1 << (i-1))]; if(RMQ[a] < RMQ[b]) best[i][j] = a; else best[i][j] = b; } } int askRMQ(int a, int b) { int t; t = mm[b-a+1]; b -= (1<<t) - 1; a = best[t][a], b = best[t][b]; return RMQ[a] < RMQ[b] ? a : b; } int lcp(int a, int b) { a = rank[a], b = rank[b]; if(a > b) swap(a, b); return height[askRMQ(a+1, b)]; }
题意:给一个字符串,以每一位为开头环形的读,把len种读法排序,排序后每种读法最后一位连在一起就是答案
思路:把数组接一段在后面,sa[i]的前一位就是排序后的最后一位。。
int main() { scanf(" %s", str); int len = strlen(str); for(int i = 0; i < len; i++) str[i+len] = str[i]; len = len<<1; da(str, sa, rank, height, len, 128); int idx = 0; for(int i = 1; i <= len; i++) if(sa[i] < (len>>1)) ans[idx++] = str[sa[i] + (len>>1) - 1]; ans[len>>1] = '