diff --git a/package.json b/package.json index c18c46b..db5a04c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "string-dsa", - "version": "1.3.2", + "version": "1.4.0", "description": "String Data Structures and Algorithms Library in JavaScript", "main": "src/index.js", "files": [ diff --git a/src/Trie.js b/src/Trie.js index db5f9a9..732621e 100644 --- a/src/Trie.js +++ b/src/Trie.js @@ -164,6 +164,44 @@ class Trie { } return res; } + + /** + * @returns {String[]} returns the ordered value of keys using BurstSort + */ + burstSort() { + const arr = []; + this._burstSortInternal(this._rootNode, arr, ""); + return arr; + } + + _burstSortInternal(node, arr, collectorString) { + let c; + if (node.$ === true) arr.push(collectorString); + + // Numerics + for (let i = 0; i < 10; i++) { + c = String(0 + i); + if (node[c] !== undefined) { + this._burstSortInternal(node[c], arr, collectorString + c); + } + } + + // Upper Case + for (let i = 0; i < 26; i++) { + c = String.fromCharCode(i + "A".charCodeAt(0)); + if (node[c] !== undefined) { + this._burstSortInternal(node[c], arr, collectorString + c); + } + } + + // Lower Case + for (let i = 0; i < 26; i++) { + c = String.fromCharCode(i + "a".charCodeAt(0)); + if (node[c] !== undefined) { + this._burstSortInternal(node[c], arr, collectorString + c); + } + } + } } module.exports = Trie; diff --git a/src/edit_distance.js b/src/edit_distance.js index d844d8f..8538268 100644 --- a/src/edit_distance.js +++ b/src/edit_distance.js @@ -28,7 +28,7 @@ function editDistance(string1, string2) { if (string1.charAt(i - 1) === string2.charAt(j - 1)) { editDistanceMatrix[i][j] = editDistanceMatrix[i - 1][j - 1]; } else { - editDistanceMatrix[i][j] = min(min(editDistanceMatrix[i - 1][j - 1], editDistanceMatrix[i][j - 1]), min(editDistanceMatrix[i][j - 1], editDistanceMatrix[i - 1][j])) + 1; + editDistanceMatrix[i][j] = min(editDistanceMatrix[i - 1][j - 1], min(editDistanceMatrix[i][j - 1], editDistanceMatrix[i - 1][j])) + 1; } } } diff --git a/src/lcs.js b/src/lcs.js index 34b682c..efc5837 100644 --- a/src/lcs.js +++ b/src/lcs.js @@ -36,7 +36,7 @@ function lcs(string1, string2) { if (string1[i1 - 1] == string2[i2 - 1]) { matchMatrix[i1][i2] = matchMatrix[i1 - 1][i2 - 1] + 1; } else { - matchMatrix[i1][i2] = max(max(matchMatrix[i1 - 1][i2 - 1], matchMatrix[i1 - 1][i2]), max(matchMatrix[i1 - 1][i2 - 1], matchMatrix[i1][i2 - 1])); + matchMatrix[i1][i2] = max(max(matchMatrix[i1][i2 - 1], matchMatrix[i1 - 1][i2]), matchMatrix[i1 - 1][i2 - 1]); } } } diff --git a/src/suffix/SuffixMain.js b/src/suffix/SuffixMain.js new file mode 100644 index 0000000..e76b2cf --- /dev/null +++ b/src/suffix/SuffixMain.js @@ -0,0 +1,100 @@ +"use strict"; + +// const Suffix = require("./src/suffix").Suffixer +// mySfx = new Suffix("marijuana") + +class Suffixer { + constructor(mainString) { + this.CHAR_LIM = 27; + this.originalString = `${mainString.toLowerCase()}$`; + + this.order = new Array(this.originalString.length); + this.class = new Array(this.originalString.length); + this.lcpArray = new Array(this.originalString.length); + this.suffixConstructed = false; + } + + charOrder() { + let charCount = new Array(this.CHAR_LIM); + for (let i = 0; i < this.CHAR_LIM; i++) charCount[i] = 0; + + for (let i = 0; i < this.originalString.length; i++) { + if (this.originalString.charAt(i) === "$") { + charCount[0] += 1; + } else { + charCount[this.originalString.charCodeAt(i) - "a".charCodeAt(0) + 1] += 1; + } + } + + for (let i = 1; i < this.CHAR_LIM; i++) { + charCount[i] += charCount[i - 1]; + } + + for (let i = this.originalString.length - 1; i >= 0; i--) { + let c; + if (this.originalString.charAt(i) === "$") { + c = 0; + } else { + c = this.originalString.charCodeAt(i) - "a".charCodeAt(0) + 1; + } + charCount[c] -= 1; + this.order[charCount[c]] = i; + } + } + + charClass() { + let pos = 0; let + classNumber = 0; + this.class[this.order[pos]] = classNumber; + pos++; + while (pos < this.originalString.length) { + if (this.originalString.charAt(this.order[pos - 1]) !== this.originalString.charAt(this.order[pos])) { + classNumber += 1; + } + this.class[this.order[pos]] = classNumber; + pos++; + } + } + + /* + sortDouble(L) { + let newOrder = new Array(this.originalString.length); + + return newOrder; + } + + updateClass(L) { + let newClass = new Array(this.originalString.length); + + return newClass; + } +*/ + + suffixArray() { + if (this.suffixConstructed) return this.order; + + let L = 1; + this.charOrder(); + this.charClass(); + while (L < this.originalString.length) { + // this.order = this.sortDouble(L); + // this.class = this.updateClass(L); + L *= 2; + } + + this.suffixConstructed = true; + return this.order; + } + + /* + lcpArray(){ + if(!this.suffixConstructed) this.suffixArray() + + for (let i=0; i< this.originalString.length; i++) this.lcpArray[i] = 0 + + // Do LCP stuff + } + */ +} + +module.exports = Suffixer; diff --git a/src/suffix/index.js b/src/suffix/index.js index e69de29..bef6606 100644 --- a/src/suffix/index.js +++ b/src/suffix/index.js @@ -0,0 +1,5 @@ +const Suffixer = require("./SuffixMain"); + +module.exports = { + Suffixer, +}; diff --git a/test/test_Trie.js b/test/test_Trie.js index 9f6cf60..28c1288 100644 --- a/test/test_Trie.js +++ b/test/test_Trie.js @@ -10,6 +10,8 @@ describe("Trie based tests", () => { const searchSpace = "can the real candy ban?"; const resultPos = [[0, 2], [13, 15], [13, 17], [19, 21]]; const existResult = [true, true, true, false]; + const orderedKeys = [st3,st1,st2]; + it("should insert a bunch of keys", () => { myT.insertList([st1, st2, st3]); assert.deepStrictEqual(myT.listAllElements(), [st1, st2, st3]); @@ -30,4 +32,9 @@ describe("Trie based tests", () => { const res = myT.containsList([st1, st2, st3, na1]); assert.deepStrictEqual(res, existResult); }); + + it("should perform burstsort properly",() =>{ + const res = myT.burstSort(); + assert.deepStrictEqual(res,orderedKeys); + }); });