| 95 | // Array Construction" by Juha K¨arkk¨ainen and Peter Sanders. |
| 96 | template <typename S> |
| 97 | void RawSkew(size_t n, size_t maxValue, S const & s, size_t * sa) |
| 98 | { |
| 99 | size_t constexpr kInvalidId = std::numeric_limits<size_t>::max(); |
| 100 | |
| 101 | if (n == 0) |
| 102 | return; |
| 103 | |
| 104 | if (n == 1) |
| 105 | { |
| 106 | sa[0] = 0; |
| 107 | return; |
| 108 | } |
| 109 | |
| 110 | size_t const n0 = (n + 2) / 3; // Number of =0 (mod 3) suffixes. |
| 111 | size_t const n1 = (n + 1) / 3; // Number of =1 (mod 3) suffixes. |
| 112 | size_t const n2 = n / 3; // Number of =2 (mod 3) suffixes. |
| 113 | |
| 114 | size_t const n02 = n0 + n2; |
| 115 | |
| 116 | size_t const fake1 = n0 != n1 ? 1 : 0; |
| 117 | |
| 118 | // The total number of =1 (mod 3) suffixes (including the fake one) |
| 119 | // is the same as the number of =0 (mod 3) suffixes. |
| 120 | ASSERT_EQUAL(n1 + fake1, n0, ()); |
| 121 | ASSERT_EQUAL(fake1, static_cast<uint32_t>(n % 3 == 1), ()); |
| 122 | |
| 123 | // Generate positions of =(1|2) (mod 3) suffixes. |
| 124 | std::vector<size_t> s12(n02 + 3); |
| 125 | std::vector<size_t> sa12(n02 + 3); |
| 126 | |
| 127 | // (n0 - n1) is needed in case when n == 0 (mod 3). We need a fake |
| 128 | // =1 (mod 3) suffix for proper sorting of =0 (mod 3) suffixes. |
| 129 | // Therefore we force here that the number of =1 (mod 3) suffixes |
| 130 | // should be the same as the number of =0 (mod 3) suffixes. That's |
| 131 | // why we need that s[n] = s[n + 1] = s[n + 2] = 0. |
| 132 | for (size_t i = 0, j = 0; i < n + fake1; ++i) |
| 133 | if (i % 3 != 0) |
| 134 | s12[j++] = i; |
| 135 | |
| 136 | // Following three lines perform a stable sorting of all triples |
| 137 | // <s[i], s[i + 1], s[i + 2]> where i =(1|2) (mod 3), including |
| 138 | // possible fake1 suffix. Final order of these triples is written to |
| 139 | // |sa12|. |
| 140 | RadixSort(n02, s12.data(), maxValue + 1, MakeSlice(s, 2), sa12.data()); |
| 141 | RadixSort(n02, sa12.data(), maxValue + 1, MakeSlice(s, 1), s12.data()); |
| 142 | RadixSort(n02, s12.data(), maxValue + 1, s, sa12.data()); |
| 143 | |
| 144 | // Generate lexicographic names for all =(1|2) (mod 3) triples. |
| 145 | size_t name = 0; |
| 146 | size_t c0 = kInvalidId; |
| 147 | size_t c1 = kInvalidId; |
| 148 | size_t c2 = kInvalidId; |
| 149 | for (size_t i = 0; i < n02; ++i) |
| 150 | { |
| 151 | auto const pos = sa12[i]; |
| 152 | if (s[pos] != c0 || s[pos + 1] != c1 || s[pos + 2] != c2) |
| 153 | { |
| 154 | c0 = s[pos]; |
no test coverage detected