forked from indy256/codelibrary
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSuffixArray2.java
More file actions
39 lines (33 loc) · 1.46 KB
/
SuffixArray2.java
File metadata and controls
39 lines (33 loc) · 1.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package strings;
import java.util.*;
import java.util.stream.IntStream;
// https://en.wikipedia.org/wiki/Suffix_array
public class SuffixArray2 {
// suffix array in O(n*log^2(n))
public static int[] suffixArray(CharSequence s) {
int n = s.length();
Integer[] sa = IntStream.range(0, n).boxed().toArray(Integer[] ::new);
int[] rank = s.chars().toArray();
for (int len = 1; len < n; len *= 2) {
long[] rank2 = new long[n];
for (int i = 0; i < n; i++) rank2[i] = ((long) rank[i] << 32) + (i + len < n ? rank[i + len] + 1 : 0);
Arrays.sort(sa, Comparator.comparingLong(a -> rank2[a]));
for (int i = 0; i < n; i++) rank[sa[i]] = i > 0 && rank2[sa[i - 1]] == rank2[sa[i]] ? rank[sa[i - 1]] : i;
}
return Arrays.stream(sa).mapToInt(Integer::intValue).toArray();
}
// random test
public static void main(String[] args) {
Random rnd = new Random(1);
for (int step = 0; step < 100000; step++) {
int n = rnd.nextInt(100);
StringBuilder s = rnd.ints(n, 0, 10).collect(
StringBuilder::new, (sb, i) -> sb.append((char) ('a' + i)), StringBuilder::append);
int[] sa = suffixArray(s);
for (int i = 0; i + 1 < n; i++)
if (s.substring(sa[i]).compareTo(s.substring(sa[i + 1])) >= 0)
throw new RuntimeException();
}
System.out.println("Test passed");
}
}