code: @Override
      public int[] buildSuffixArray(int[] input, int start, int length) {
          Tools.assertAlways(input != null, "input must not be null");
          Tools.assertAlways(length >= 2, "input length must be >= 2");
          Tools.assertAlways(input.length >= start + length + 3, "no extra space after input end");
          assert Tools.allPositive(input, start, length);
  
          final int alphabetSize = Tools.max(input, start, length);
          final int[] SA = new int[length + 3];
  
          // Preserve the tail of the input (destroyed when constructing the array).
          final int[] tail = new int[3];
          System.arraycopy(input, start + length, tail, 0, 3);
          Arrays.fill(input, start + length, start + length + 3, 0);
  
          suffixArray(input, SA, length, alphabetSize, start, new int[alphabetSize + 2]);
  
          // Reconstruct the input's tail.
          System.arraycopy(tail, 0, input, start + length, 3);
          return SA;
      }
docs: {@inheritDoc}
  <p>
  Additional constraints enforced by Karkkainen-Sanders algorithm:
  <ul>
  <li>non-negative (&gt;0) symbols in the input (because of radix sort)</li>
  <li><code>input.length</code> &gt;= <code>start + length + 3</code> (to simplify
  border cases)</li>
  <li>length &gt;= 2</li>
  </ul>
  <p>
  If the input contains zero or negative values, or has no extra trailing cells,
  adapters can be used in the following way:
  <p>
  <pre>
  return new {@link DensePositiveDecorator}(
  new {@link ExtraTrailingCellsDecorator}(
  new {@link Skew}(), 3));
  </pre>
  
  @see ExtraTrailingCellsDecorator
  @see DensePositiveDecorator