介绍用DC3算法生成后缀数组的流程
1.得到S12的精确排名(取S12的前三位进行桶排序)
2.s1按照原来在数组的顺序放在左边(放第一步的排名),s2按照原来在数组的顺序放在右边中间(放第一步的排名)用最小的ASCII隔开(如果第一步得到精确的排名,跳过第2步)
3.得到s0精确排名(每一个S0的数变为S0位置的数 + 紧跟当前位置数的排名)
4.得到总排名(S0和S12进行merge,如果是S0和S1merge:S0和S1当前位置的数字做比较,下一位用S12的排名做比较,如果是S0和S2merge:S0和S1当前位置的数字做比较,下一位还用当前字符做比较,下下一位用排名做比较)
DC3模板
// arr = [a,a,b,a]
// 0 1 2 3
// 第几名在原数组的位置
// sa = [3,0,1,2]
// 0 1 2 3
// 原数组位置是第几名
// rank = [1,2,3,0]
// 0 1 2 3
public int[] sa;
public int[] rank;
public int[] height;
// 构造方法的约定:
// 数组叫nums,如果你是字符串,请转成整型数组nums
// 数组中,最小值>=1
// 如果不满足,处理成满足的,也不会影响使用
// max, nums里面最大值是多少
public DC3(int[] nums, int max) {
sa = sa(nums, max);
rank = rank();
height = height(nums);
}
private int[] sa(int[] nums, int max) {
int n = nums.length;
int[] arr = new int[n + 3];
for (int i = 0; i < n; i++) {
arr[i] = nums[i];
}
return skew(arr, n, max);
}
private int[] skew(int[] nums, int n, int K) {
int n0 = (n + 2) / 3, n1 = (n + 1) / 3, n2 = n / 3, n02 = n0 + n2;
int[] s12 = new int[n02 + 3], sa12 = new int[n02 + 3];
for (int i = 0, j = 0; i < n + (n0 - n1); ++i) {
if (0 != i % 3) {
s12[j++] = i;
}
}
radixPass(nums, s12, sa12, 2, n02, K);
radixPass(nums, sa12, s12, 1, n02, K);
radixPass(nums, s12, sa12, 0, n02, K);
int name = 0, c0 = -1, c1 = -1, c2 = -1;
for (int i = 0; i < n02; ++i) {
if (c0 != nums[sa12[i]] || c1 != nums[sa12[i] + 1] || c2 != nums[sa12[i] + 2]) {
name++;