1+ import java .util .Arrays ;
2+
13class StringAlgorithm {
24 private static int [] saNaive (int [] s ) {
35 int n = s .length ;
4- Integer [] _sa = new Integer [n ];
5- for (int i = 0 ; i < n ; i ++) {
6- _sa [i ] = i ;
6+ int [] sa = new int [n ];
7+ for (int i = 0 ;i < n ;i ++){
8+ sa [i ] = i ;
79 }
8- java . util . Arrays . sort ( _sa , (l , r ) -> {
10+ insertionsortUsingComparator ( sa , (l , r ) -> {
911 while (l < n && r < n ) {
1012 if (s [l ] != s [r ]) return s [l ] - s [r ];
1113 l ++;
1214 r ++;
1315 }
1416 return -(l - r );
1517 });
16- int [] sa = new int [n ];
17- for (int i = 0 ; i < n ; i ++) {
18- sa [i ] = _sa [i ];
19- }
2018 return sa ;
2119 }
2220
2321 private static int [] saDoubling (int [] s ) {
2422 int n = s .length ;
25- Integer [] _sa = new Integer [n ];
26- for (int i = 0 ; i < n ; i ++) {
27- _sa [i ] = i ;
23+ int [] sa = new int [n ];
24+ for (int i = 0 ;i < n ;i ++){
25+ sa [i ] = i ;
2826 }
2927 int [] rnk = s ;
3028 int [] tmp = new int [n ];
3129
3230 for (int k = 1 ; k < n ; k *= 2 ) {
3331 final int _k = k ;
3432 final int [] _rnk = rnk ;
35- java .util .Comparator < Integer > cmp = (x , y ) -> {
33+ java .util .function . IntBinaryOperator cmp = (x , y ) -> {
3634 if (_rnk [x ] != _rnk [y ]) return _rnk [x ] - _rnk [y ];
3735 int rx = x + _k < n ? _rnk [x + _k ] : -1 ;
3836 int ry = y + _k < n ? _rnk [y + _k ] : -1 ;
3937 return rx - ry ;
4038 };
41- java . util . Arrays . sort ( _sa , cmp );
42- tmp [_sa [0 ]] = 0 ;
39+ mergesortUsingComparator ( sa , cmp );
40+ tmp [sa [0 ]] = 0 ;
4341 for (int i = 1 ; i < n ; i ++) {
44- tmp [_sa [i ]] = tmp [_sa [i - 1 ]] + (cmp .compare ( _sa [i - 1 ], _sa [i ]) < 0 ? 1 : 0 );
42+ tmp [sa [i ]] = tmp [sa [i - 1 ]] + (cmp .applyAsInt ( sa [i - 1 ], sa [i ]) < 0 ? 1 : 0 );
4543 }
4644 int [] buf = tmp ;
4745 tmp = rnk ;
4846 rnk = buf ;
4947 }
48+ return sa ;
49+ }
5050
51- int [] sa = new int [n ];
52- for (int i = 0 ; i < n ; i ++) {
53- sa [i ] = _sa [i ];
51+ private static void insertionsortUsingComparator (int [] a , java .util .function .IntBinaryOperator comparator ) {
52+ final int n = a .length ;
53+ for (int i = 1 ; i < n ; i ++) {
54+ final int tmp = a [i ];
55+ if (comparator .applyAsInt (a [i - 1 ], tmp ) > 0 ) {
56+ int j = i ;
57+ do {
58+ a [j ] = a [j - 1 ];
59+ j --;
60+ } while (j > 0 && comparator .applyAsInt (a [j - 1 ], tmp ) > 0 );
61+ a [j ] = tmp ;
62+ }
5463 }
55- return sa ;
5664 }
5765
58- private static final int THRESHOLD_NAIVE = 10 ;
59- private static final int THRESHOLD_DOUBLING = 40 ;
66+ private static void mergesortUsingComparator (int [] a , java .util .function .IntBinaryOperator comparator ) {
67+ final int n = a .length ;
68+ final int [] work = new int [n ];
69+ for (int block = 1 ; block <= n ; block <<= 1 ) {
70+ final int block2 = block << 1 ;
71+ for (int l = 0 , max = n - block ; l < max ; l += block2 ) {
72+ int m = l + block ;
73+ int r = Math .min (l + block2 , n );
74+ System .arraycopy (a , l , work , 0 , block );
75+ for (int i = l , wi = 0 , ti = m ;; i ++) {
76+ if (ti == r ) {
77+ System .arraycopy (work , wi , a , i , block - wi );
78+ break ;
79+ }
80+ if (comparator .applyAsInt (work [wi ], a [ti ]) > 0 ) {
81+ a [i ] = a [ti ++];
82+ } else {
83+ a [i ] = work [wi ++];
84+ if (wi == block ) break ;
85+ }
86+ }
87+ }
88+ }
89+ }
90+
91+ private static final int THRESHOLD_NAIVE = 50 ;
92+ private static final int THRESHOLD_DOUBLING = 0 ;
6093
6194 private static int [] sais (int [] s , int upper ) {
6295 int n = s .length ;
@@ -72,9 +105,9 @@ private static int[] sais(int[] s, int upper) {
72105 if (n < THRESHOLD_NAIVE ) {
73106 return saNaive (s );
74107 }
75- if (n < THRESHOLD_DOUBLING ) {
76- return saDoubling (s );
77- }
108+ // if (n < THRESHOLD_DOUBLING) {
109+ // return saDoubling(s);
110+ // }
78111
79112 int [] sa = new int [n ];
80113 boolean [] ls = new boolean [n ];
@@ -195,22 +228,22 @@ public static int[] suffixArray(int[] s, int upper) {
195228 return sais (s , upper );
196229 }
197230
198- public static int [] suffixArray (int [] s ) {
231+ public static int [] suffixArray (int [] s )
232+ {
199233 int n = s .length ;
200- Integer [] idx = new Integer [n ];
201- for (int i = 0 ; i < n ; i ++) {
202- idx [i ] = i ;
234+ int [] vals = Arrays .copyOf (s , n );
235+ java .util .Arrays .sort (vals );
236+ int p = 1 ;
237+ for (int i = 1 ;i < n ;i ++){
238+ if (vals [i ] != vals [i -1 ]){
239+ vals [p ++] = vals [i ];
240+ }
203241 }
204- java .util .Arrays .sort (idx , (l , r ) -> s [l ] - s [r ]);
205242 int [] s2 = new int [n ];
206- int now = 0 ;
207- for (int i = 0 ; i < n ; i ++) {
208- if (i > 0 && s [idx [i - 1 ]] != s [idx [i ]]) {
209- now ++;
210- }
211- s2 [idx [i ]] = now ;
243+ for (int i = 0 ;i < n ;i ++){
244+ s2 [i ] = java .util .Arrays .binarySearch (vals , 0 , p , s [i ]);
212245 }
213- return sais (s2 , now );
246+ return sais (s2 , p );
214247 }
215248
216249 public static int [] suffixArray (char [] s ) {
0 commit comments