后缀数组模板/LCP模板
1 //后缀数组模板,MANX为数组的大小 2 //支持的操作有计算后缀数组(sa数组), 计算相邻两元素的最长公共前缀(height数组),使用get_height(); 3 //计算两个后缀a, 和b的最长公共前缀,请先使用lcp_init(),再调用get_lcp(a, b)得到 4 //下面的n是输入字符串的长度+1(n = strlen(s) + 1), m是模板的范围 m=128表示在字母,数字范围内,可以扩大也可缩小 5 //s[len] 是插入的一个比输入字符都要小的字符 6 struct SufArray { 7 char s[MAXN]; 8 int sa[MAXN], t[MAXN], t2[MAXN], c[MAXN], n, m; 9 int rnk[MAXN], height[MAXN];//rnk和height数组 10 int mi[MAXN][20], idxK[MAXN];//用于计算LCP 11 12 void init() { 13 mem0(s); 14 mem0(height); 15 } 16 //读入字符串作为输入 17 void read_str() { 18 gets(s); 19 m = 128; 20 n = strlen(s); 21 s[n++] = ' '; 22 } 23 void build_sa() { 24 int *x = t, *y = t2; 25 rep (i, 0, m - 1) c[i] = 0; 26 rep (i, 0, n - 1) c[x[i] = s[i]] ++; 27 rep (i, 1, m - 1) c[i] += c[i - 1]; 28 dec (i, n - 1, 0) sa[--c[x[i]]] = i; 29 for(int k = 1; k <= n; k <<= 1) { 30 int p = 0; 31 rep (i, n - k, n - 1) y[p++] = i; 32 rep (i, 0, n - 1) if(sa[i] >= k) y[p++] = sa[i] - k; 33 rep (i, 0, m - 1) c[i] = 0; 34 rep (i, 0, n - 1) c[x[y[i]]] ++; 35 rep (i, 0, m - 1) c[i] += c[i - 1]; 36 dec (i, n - 1, 0) sa[--c[x[y[i]]]] = y[i]; 37 swap(x, y); 38 p = 1; 39 x[sa[0]] = 0; 40 rep (i, 1, n - 1) { 41 x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++; 42 } 43 if(p >= n) break; 44 m = p; 45 } 46 } 47 void get_height() { 48 int k = 0; 49 rep (i, 0, n - 1) rnk[sa[i]] = i; 50 rep (i, 0, n - 1) { 51 if(k) k --; 52 int j = sa[rnk[i] - 1]; 53 while(s[i + k] == s[j + k]) k ++; 54 height[rnk[i]] = k; 55 } 56 } 57 void rmq_init(int *a, int n) { 58 rep (i, 0, n - 1) mi[i][0] = a[i]; 59 for(int j = 1; (1 << j) <= n; j ++) { 60 for(int i = 0; i + (1<<j) - 1 < n; i ++) { 61 mi[i][j] = min(mi[i][j - 1], mi[i + (1 << (j - 1))][j - 1]); 62 } 63 } 64 rep (len, 1, n) { 65 idxK[len] = 0; 66 while((1 << (idxK[len] + 1)) <= len) idxK[len] ++; 67 } 68 } 69 int rmq_min(int l, int r) { 70 int len = r - l + 1, k = idxK[len]; 71 return min(mi[l][k], mi[r - (1 << k) + 1][k]); 72 } 73 void lcp_init() { 74 get_height(); 75 rmq_init(height, n); 76 } 77 int get_lcp(int a, int b) { 78 if(a == b) return n - a - 1; 79 return rmq_min(min(rnk[a], rnk[b]) + 1, max(rnk[a], rnk[b])); 80 } 81 void solve() { 82 } 83 };