SHOW:
|
|
- or go back to the newest paste.
| 1 | // lexicographic order for pairs | |
| 2 | inline bool leq(int a1, int a2, int b1, int b2) {
| |
| 3 | return(a1 < b1 || a1 == b1 && a2 <= b2); | |
| 4 | } | |
| 5 | ||
| 6 | // and triples | |
| 7 | inline bool leq(int a1, int a2, int a3, int b1, int b2, int b3) {
| |
| 8 | return(a1 < b1 || a1 == b1 && leq(a2,a3, b2,b3)); | |
| 9 | } // and triples | |
| 10 | ||
| 11 | // stably sort a[0..n-1] to b[0..n-1] with keys in 0..K from r | |
| 12 | static void radixPass(int* a, int* b, int* r, int n, int K) {// count occurrences
| |
| 13 | int* c = new int[K + 1]; // counter array | |
| 14 | for (int i = 0; i <= K; i++) c[i] = 0; // reset counters | |
| 15 | for (int i = 0; i < n; i++) c[r[a[i]]]++; // count occurrences | |
| 16 | for (int i = 0, sum = 0; i <= K; i++) // exclusive prefix sums | |
| 17 | {
| |
| 18 | int t = c[i]; | |
| 19 | c[i] = sum; | |
| 20 | sum += t; | |
| 21 | } | |
| 22 | for (int i = 0; i < n; i++) b[c[r[a[i]]]++] = a[i]; // sort | |
| 23 | delete [] c; | |
| 24 | } | |
| 25 | ||
| 26 | // find the suffix array SA of s[0..n-1] in {1..K}ˆn
| |
| 27 | // require s[n]=s[n+1]=s[n+2]=0, n>=2 | |
| 28 | void suffixArray(int* s, int* SA, int n, int K) {
| |
| 29 | int n0 = (n+2)/3, n1 = (n+1)/3, n2 = n/3, n02 = n0+n2; | |
| 30 | int* s12 = new int[n02+3]; s12[n02] = s12[n02+1] = s12[n02+2] = 0; | |
| 31 | int* SA12 = new int[n02+3]; SA12[n02] = SA12[n02+1] = SA12[n02+2] = 0; | |
| 32 | int* s0 = new int[n0]; | |
| 33 | int* SA0 = new int[n0]; | |
| 34 | // generate positions of mod 1 and mod 2 suffixes | |
| 35 | // the "+(n0-n1)" adds a dummy mod 1 suffix if n%3 == 1 | |
| 36 | for (int i=0, j=0; i < n + (n0-n1); i++) | |
| 37 | if (i%3 != 0) s12[j++] = i; | |
| 38 | // lsb radix sort the mod 1 and mod 2 triples | |
| 39 | radixPass(s12 , SA12, s+2, n02, K); | |
| 40 | radixPass(SA12, s12 , s+1, n02, K); | |
| 41 | radixPass(s12 , SA12, s , n02, K); | |
| 42 | // find lexicographic names of triples | |
| 43 | int name = 0, c0 = -1, c1 = -1, c2 = -1; | |
| 44 | for (int i = 0; i < n02; i++) {
| |
| 45 | if (s[SA12[i]] != c0 || s[SA12[i]+1] != c1 || s[SA12[i]+2] != c2) {
| |
| 46 | name++; | |
| 47 | c0 = s[SA12[i]]; | |
| 48 | c1 = s[SA12[i]+1]; | |
| 49 | c2 = s[SA12[i]+2]; | |
| 50 | } | |
| 51 | if (SA12[i]%3 == 1) s12[SA12[i]/3] = name; // left half | |
| 52 | else s12[SA12[i]/3 + n0] = name; // right half | |
| 53 | } | |
| 54 | // recurse if names are not yet unique | |
| 55 | if (name < n02) {
| |
| 56 | suffixArray(s12, SA12, n02, name); | |
| 57 | // store unique names in s12 using the suffix array | |
| 58 | for (int i = 0; i < n02; i++) s12[SA12[i]] = i + 1; | |
| 59 | } else // generate the suffix array of s12 directly | |
| 60 | for (int i = 0; i < n02; i++) SA12[s12[i] - 1] = i; | |
| 61 | // stably sort the mod 0 suffixes from SA12 by their first character | |
| 62 | for (int i = 0, j = 0; i < n02; i++) | |
| 63 | if (SA12[i] < n0) s0[j++] = 3*SA12[i]; | |
| 64 | radixPass(s0, SA0, s, n0, K); | |
| 65 | // merge sorted SA0 suffixes and sorted SA12 suffixes | |
| 66 | for (int p = 0, t = n0-n1, k = 0; k < n; k++) {
| |
| 67 | #define GetI() (SA12[t] < n0 ? SA12[t] * 3 + 1 : (SA12[t] - n0) * 3 + 2) | |
| 68 | int i = GetI(); // pos of current offset 12 suffix | |
| 69 | int j = SA0[p]; // pos of current offset 0 suffix | |
| 70 | if (SA12[t] < n0 ? // different compares for mod 1 and mod 2 suffixes | |
| 71 | leq(s[i], s12[SA12[t] + n0], s[j], s12[j/3]) : | |
| 72 | leq(s[i],s[i+1],s12[SA12[t]-n0+1], s[j],s[j+1],s12[j/3+n0])) | |
| 73 | {// suffix from SA12 is smaller
| |
| 74 | SA[k] = i; t++; | |
| 75 | if (t == n02) // done --- only SA0 suffixes left | |
| 76 | for (k++; p < n0; p++, k++) SA[k] = SA0[p]; | |
| 77 | } else {// suffix from SA0 is smaller
| |
| 78 | SA[k] = j; p++; | |
| 79 | if (p == n0) // done --- only SA12 suffixes left | |
| 80 | for (k++; t < n02; t++, k++) SA[k] = GetI(); | |
| 81 | } | |
| 82 | } | |
| 83 | delete [] s12; delete [] SA12; delete [] SA0; delete [] s0; | |
| 84 | } | |
| 85 | ||
| 86 | int main() {
| |
| 87 | ||
| 88 | return 0; | |
| 89 | } |