Example #1
0
 // find the suffix array SA of s[0..n-1] in {1..K}^n
 // require s[n]=s[n+1]=s[n+2]=0, n>=2
 static void suffixArray(int[] s, int[] SA, int n, int K) {
   int n0 = (n + 2) / 3, n1 = (n + 1) / 3, n2 = n / 3, n02 = n0 + n2;
   int[] s12 = new int[n02 + 3];
   s12[n02] = s12[n02 + 1] = s12[n02 + 2] = 0;
   int[] SA12 = new int[n02 + 3];
   SA12[n02] = SA12[n02 + 1] = SA12[n02 + 2] = 0;
   int[] s0 = new int[n0];
   int[] SA0 = new int[n0];
   for (int i = 0, j = 0; i < n + (n0 - n1); i++) if (i % 3 != 0) s12[j++] = i;
   radixPass(s12, SA12, s, n02, K, 2);
   radixPass(SA12, s12, s, n02, K, 1);
   radixPass(s12, SA12, s, n02, K, 0);
   int name = 0, c0 = -1, c1 = -1, c2 = -1;
   for (int i = 0; i < n02; i++) {
     if (s[SA12[i]] != c0 || s[SA12[i] + 1] != c1 || s[SA12[i] + 2] != c2) {
       name++;
       c0 = s[SA12[i]];
       c1 = s[SA12[i] + 1];
       c2 = s[SA12[i] + 2];
     }
     if (SA12[i] % 3 == 1) s12[SA12[i] / 3] = name;
     else s12[SA12[i] / 3 + n0] = name;
   }
   if (name < n02) {
     suffixArray(s12, SA12, n02, name);
     for (int i = 0; i < n02; i++) s12[SA12[i]] = i + 1;
   } else for (int i = 0; i < n02; i++) SA12[s12[i] - 1] = i;
   for (int i = 0, j = 0; i < n02; i++) if (SA12[i] < n0) s0[j++] = 3 * SA12[i];
   radixPass(s0, SA0, s, n0, K, 0);
   for (int p = 0, t = n0 - n1, k = 0; k < n; k++) {
     int i = (SA12[t] < n0 ? SA12[t] * 3 + 1 : (SA12[t] - n0) * 3 + 2);
     int j = SA0[p];
     if (SA12[t] < n0
         ? leq(s[i], s12[SA12[t] + n0], s[j], s12[j / 3])
         : leq(s[i], s[i + 1], s12[SA12[t] - n0 + 1], s[j], s[j + 1], s12[j / 3 + n0])) {
       SA[k] = i;
       t++;
       if (t == n02) for (k++; p < n0; p++, k++) SA[k] = SA0[p];
     } else {
       SA[k] = j;
       p++;
       if (p == n0)
         for (k++; t < n02; t++, k++)
           SA[k] = (SA12[t] < n0 ? SA12[t] * 3 + 1 : (SA12[t] - n0) * 3 + 2);
     }
   }
 }