[BZOJ1031][JSOI2007]字符加密Cipher(后缀数组)
算是个模板。
题目说循环,那就再复制一串拼接上。
然后求后缀数组,再搞就可以。
虽然是求后缀,会在后面多一些字符串,然而题目中说的是循环一圈,但是没有影响。
——代码
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define N 200005 5 6 int m = 'z' + 1; 7 int len, buc[N], x[N], y[N], sa[N]; 8 char s[N]; 9 10 inline void build_sa() 11 { 12 int i, k, p; 13 for(i = 0; i < m; i++) buc[i] = 0; 14 for(i = 0; i < len; i++) buc[x[i] = s[i]]++; 15 for(i = 1; i < m; i++) buc[i] += buc[i - 1]; 16 for(i = len - 1; i >= 0; i--) sa[--buc[x[i]]] = i; 17 for(k = 1; k <= len; k <<= 1) 18 { 19 p = 0; 20 for(i = len - 1; i >= len - k; i--) y[p++] = i; 21 for(i = 0; i < len; i++) if(sa[i] >= k) y[p++] = sa[i] - k; 22 for(i = 0; i < m; i++) buc[i] = 0; 23 for(i = 0; i < len; i++) buc[x[y[i]]]++; 24 for(i = 1; i < m; i++) buc[i] += buc[i - 1]; 25 for(i = len - 1; i >= 0; i--) sa[--buc[x[y[i]]]] = y[i]; 26 std::swap(x, y); 27 p = 1, x[sa[0]] = 0; 28 for(i = 1; i < len; i++) 29 x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++; 30 if(p >= len) break; 31 m = p; 32 } 33 } 34 35 int main() 36 { 37 int i; 38 scanf("%s", s); 39 len = strlen(s); 40 for(i = len; i < (len << 1); i++) s[i] = s[i - len]; 41 len <<= 1; 42 build_sa(); 43 len >>= 1; 44 for(i = 0; i < (len << 1); i++) 45 if(sa[i] < len) 46 printf("%c", s[sa[i] + len - 1]); 47 return 0; 48 }