You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.6 KiB
94 lines
2.6 KiB
"use strict"; |
|
Object.defineProperty(exports, "__esModule", { value: true }); |
|
exports.consolidate = void 0; |
|
const TrieNode_1 = require("./TrieNode"); |
|
/** |
|
* Consolidate to DAWG |
|
* @param root the root of the Trie tree |
|
*/ |
|
function consolidate(root) { |
|
let count = 0; |
|
const signatures = new Map(); |
|
const cached = new Map(); |
|
const knownMap = new Map(); |
|
function signature(n) { |
|
const isWord = n.f ? '*' : ''; |
|
const ref = n.c ? JSON.stringify([...n.c.entries()].map(([k, n]) => [k, cached.get(n)])) : ''; |
|
return isWord + ref; |
|
} |
|
function findEow(n) { |
|
if (n.f && !n.c) |
|
return n; |
|
let r; |
|
// istanbul ignore else |
|
if (n.c) { |
|
for (const c of n.c.values()) { |
|
r = findEow(c); |
|
// istanbul ignore else |
|
if (r) |
|
break; |
|
} |
|
} |
|
return r; |
|
} |
|
function compareMaps(a, b) { |
|
for (const e of a) { |
|
if (b.get(e[0]) !== e[1]) |
|
return false; |
|
} |
|
return a.length === b.size; |
|
} |
|
function deepCopy(n) { |
|
if (knownMap.has(n)) { |
|
return knownMap.get(n); |
|
} |
|
const orig = n; |
|
if (n.c) { |
|
const children = [...n.c].map((c) => [c[0], deepCopy(c[1])]); |
|
if (!compareMaps(children, n.c)) { |
|
n = { f: n.f, c: new Map(children) }; |
|
} |
|
} |
|
const sig = signature(n); |
|
const ref = signatures.get(sig); |
|
if (ref) { |
|
knownMap.set(orig, ref); |
|
return ref; |
|
} |
|
Object.freeze(n); |
|
signatures.set(sig, n); |
|
cached.set(n, count++); |
|
knownMap.set(orig, n); |
|
return n; |
|
} |
|
function process(n) { |
|
if (cached.has(n)) { |
|
return n; |
|
} |
|
if (Object.isFrozen(n)) { |
|
return knownMap.get(n) || deepCopy(n); |
|
} |
|
if (n.c) { |
|
const children = [...n.c] |
|
.sort((a, b) => (a[0] < b[0] ? -1 : 1)) |
|
.map((c) => [c[0], process(c[1])]); |
|
n.c = new Map(children); |
|
} |
|
const sig = signature(n); |
|
const ref = signatures.get(sig); |
|
if (ref) { |
|
return ref; |
|
} |
|
signatures.set(sig, n); |
|
cached.set(n, count++); |
|
return n; |
|
} |
|
// Add end of word to the set of signatures and cache it. |
|
const eow = findEow(root) || { f: TrieNode_1.FLAG_WORD, c: undefined }; |
|
signatures.set(signature(eow), eow); |
|
cached.set(eow, count++); |
|
root = process(root); |
|
return root; |
|
} |
|
exports.consolidate = consolidate; |
|
//# sourceMappingURL=consolidate.js.map
|