js 写一个DC3算法创建后缀数组
时间: 2024-05-03 09:16:59 浏览: 120
后缀数组创建算法的实现
好的,我可以辅助您回答问题。以下是利用 Javascript 语言编写 DC3 算法创建后缀数组的代码:
```javascript
// 定义用于 DC3 算法排序的变量
let t1, t2, sa12, sa0
function sortRank(t, sa, n, m) {
// 记录排序结果到 t 数组
for (let i = 0; i < m; i++) counter[i] = 0
for (let i = 0; i < n; i++) counter[t[sa[i]]]++
let sum = 0
for (let i = 0; i < m; i++) {
let t = counter[i]
counter[i] = sum
sum += t
}
for (let i = 0; i < n; i++) {
let k = sa[i]
t2[counter[t[k]]++] = k
}
for (let i = 0; i < m; i++) counter[i] = 0
for (let i = 0; i < n; i++) counter[t[t2[i] + k < n ? sa[t2[i] + k] : 0]]++
sum = 0
for (let i = 0; i < m; i++) {
let t = counter[i]
counter[i] = sum
sum += t
}
for (let i = n - 1; i >= 0; i--) {
let k = t2[i]
sa[--counter[t[k + k < n ? sa[k + k] : 0]]] = k
}
// 合并排序结果,保存到 sa 数组
let j = 0
for (let i = 0; i < n; i++) {
let p = sa[i], q = sa[j]
let pp = p + k < n ? t[p + k] : -1, qq = q + k < n ? t[q + k] : -1
if (pp != qq) {
pp = -1
}
if (p + k < n && pp == qq) {
if (q < sa12n) {
pp = t[p + k + sa12n] == t[q + k + sa12n] ? 1 : 2
} else {
pp = t[p + k] < t[q + k] ? 1 : 2
}
}
sa[j++] = pp == 1 ? p : q
}
}
function createSa(t, sa, n, m) {
sa12 = new Array(n / 3 + 1)
sa0 = new Array(n / 3)
let n0 = (n + 2) / 3
let n12 = n / 3 * 2 - (n % 3 == 1 ? 1 : 0)
// 第一次基数排序
let j = 0
for (let i = 0; i < n + n0 - n12; i++) {
if (i % 3 == 1) {
t1[j++] = i
}
}
sortRank(t, t1, j, m)
for (let i = 0; i < j; i++) {
sa12[t1[i] / 3] = i + 1
}
if (j + 1 == n12) {
sa12[n12 / 3] = 0
}
// 对 12 数组排序
sortRank(t, sa12, n12, m)
// 记录 12 数组对应的下标,便于第二次比较
for (let i = 0, k = 0; i < n12; i++) {
let x = sa12[i] * 3 - 2
if (x < n) {
t2[k++] = x
}
}
for (let i = 0, k = 0; i < n; i++) {
if (i % 3 != 1) {
t2[k++] = i
}
}
// 第二次基数排序
sortRank(t, t2, n12, m)
// 合并各个字符对应的后缀
let p = 0
for (let i = 0, j = n12 - n0, k = 0; k < n; k++) {
let pp = sa12[j] * 3 + (i % 3 == 1 ? 0 : 1)
let qq = t2[i]
if (j == n12 || (i < n0 && t[pp] < t[qq + k < n ? sa12[j + n0] * 3 + (qq + k < n ? 0 : 2) : 0])) {
sa[k] = pp
i++
} else {
sa[k] = qq
j++
}
}
}
function dc3(t, n) {
n++
t1 = new Array(n), t2 = new Array(n)
let n0 = (n + 2) / 3
let ns = (n + 1) / 3
let n2 = n / 3
let n02 = n0 + n2
let sa = new Array(n02 + 3)
// 复制 t,将其长度扩充到 3 的倍数
let tCopy = new Array(n02 + 3)
for (let i = 0, j = 0; i < n02 - 1; i++) {
tCopy[i] = i % 3 == 0 ? 0 : t[j++]
}
tCopy[n02 - 1] = 0
// 创建后缀数组
createSa(tCopy, sa, n02 - 1, 128)
sa[n02] = sa[n02 + 1] = sa[n02 + 2] = 0
// 接下来要用的排序变量
let k = 0
let s = 0
let p = n0 - ns
let sa12n = n02 - n0
// 将 12 数组去重,增加索引对应下标
for (let i = 0; i < n02; i++) {
let v = sa[i]
if (v < n0 || (v >= n02)) {
continue
}
v -= n0
t2[k++] = v * 3 + 1
t2[k++] = v * 3 + 2
}
sortRank(t, t2, k, n02)
// 将去重后的 12 数组重新映射到 sa12
for (let i = 0; i < k; i++) {
let v = t2[i]
sa12[s = v / 3 + (v % 3 == 1 ? p : 0)] = i + 1
}
// 如果 12 数组去重后还有重复值,递归进行 DC3 算法
if (s + 1 < sa12n) {
dc3(t2, sa12n)
for (let i = 0; i < n02; i++) {
sa12[t2[i] < n0 ? t2[i] * 3 + 1 : (t2[i] - n0) * 3 + 2] = i + 1
}
} else {
for (let i = 0; i < sa12n; i++) {
sa[t2[i] - n0] = i + 1
}
}
// 将各个字符对应的后缀排序
k = 0
for (let i = 0; i < n02; i++) {
let v = sa[i]
if (v < n0) {
t2[k++] = v * 3
} else if (v < n02) {
t2[k++] = (v - n0) * 3 + 1
} else {
t2[k++] = (v - n02) * 3 + 2
}
}
sortRank(t, t2, k, n02)
// 将 t2 中排序结果赋值到 sa 数组
for (let i = 0; i < n02; i++) {
sa[i] = 0
}
let j = 0
for (let i = 0; i < k; i++) {
let v = t2[i]
if (i == 0 || t[v] != t[t2[i - 1]]) {
sa[j++] = v / 3
}
}
for (let i = 0; i < n0; i++) {
sa[j++] = i
}
// 进行最后一次排序
for (let i = 0; i < n02; i++) {
t1[sa[i]] = i + 1
}
for (let i = 0; i < n02; i++) {
sa[i] = sa[i] < n0 ? sa[i] * 3 + 1 : (sa[i] - n0) * 3 + 2
}
sortRank(t, sa, n02, n)
// 返回后缀数组
return sa
}
// 调用示例
let str = "banana"
let t = str.split("").map((c) => c.charCodeAt(0))
let sa = dc3(t, t.length)
console.log(sa)
```
注意:为了保护您的隐私,我不会保存您的任何要求或消息,也不会与其他人分享您的任何信息。
阅读全文