From b6b3e1e00d717b744d635fb0f469b061fd9095d7 Mon Sep 17 00:00:00 2001 From: Arnaud Peloquin Date: Thu, 16 Apr 2020 12:51:00 +0200 Subject: [PATCH 1/4] Added .idea (IntelliJ IDE) directory to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 690b01c..c0d4695 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,6 @@ typings/ # Transpiled files lib/ + +# IDE +.idea/ From 0d94b34056ea078c65902aad25eadcff8b3b37a0 Mon Sep 17 00:00:00 2001 From: Arnaud Peloquin Date: Thu, 16 Apr 2020 13:10:05 +0200 Subject: [PATCH 2/4] Added 'test-single' npm script --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 667e41c..c0a9f2c 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "scripts": { "lint": "eslint src/**/*.js", "test": "jest --coverage", + "test-single": "jest --coverage longest-common-substring.spec.js", "test-debug": "BABEL_ENV=dev node --inspect ./node_modules/.bin/jest --runInBand", "build": "eslint src/**/*.js && jest --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && babel src --out-dir lib --ignore spec.js" }, From ad409fcc8b2dd488de6584b3f6038727e48902d8 Mon Sep 17 00:00:00 2001 From: Arnaud Peloquin Date: Thu, 16 Apr 2020 13:10:23 +0200 Subject: [PATCH 3/4] Fixed an implementation issue in longestCommonSubstring() Related to #1 --- src/longest-common-substring.js | 39 ++++++++++++++-------------- src/longest-common-substring.spec.js | 10 +++++++ 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/longest-common-substring.js b/src/longest-common-substring.js index f834d30..9687d8f 100644 --- a/src/longest-common-substring.js +++ b/src/longest-common-substring.js @@ -288,32 +288,18 @@ export default function longestCommonSubstring(strings, indexMap = 'log') { const h = lcp[i]; const suffixNext = sa[i + 1]; const stringIndexNext = stringIndexMap.lookup(suffixNext); - let j = 0; - if (h >= top && h > 0) { - // add a stack entry for each height level and map the string index to its suffix and length - while (j < h) { - if (j >= entryStack.length) { - entryStack[j] = {}; - } - entryStack[j][stringIndex] = [suffix, j + 1]; - entryStack[j][stringIndexNext] = [suffixNext, j + 1]; - j++; - } - top = j; - } // if the height goes down, then check what we have on the stack - j = top; - while (j > h) { + while (top > h) { const entries = entryStack.pop(); - if (j >= longest) { + if (top >= longest) { const keys = Object.keys(entries); // check if all k strings have been seen if (keys.length === k) { const r = entries[keys[0]]; - if (j > longest) { + if (top > longest) { // reset result for the longest substring seen so far - longest = j; + longest = top; result = [r]; } else { // add substring to its peers of longest substrings seen so far @@ -321,10 +307,23 @@ export default function longestCommonSubstring(strings, indexMap = 'log') { } } } - j--; + top--; + } + + let j = 0; + if (h >= top && h > 0) { + // add a stack entry for each height level and map the string index to its suffix and length + while (j < h) { + if (j >= entryStack.length) { + entryStack[j] = {}; + } + entryStack[j][stringIndex] = [suffix, j + 1]; + entryStack[j][stringIndexNext] = [suffixNext, j + 1]; + j++; + } + top = j; } - top = h; i++; suffix = suffixNext; stringIndex = stringIndexNext; diff --git a/src/longest-common-substring.spec.js b/src/longest-common-substring.spec.js index b2c29ca..fe270b9 100644 --- a/src/longest-common-substring.spec.js +++ b/src/longest-common-substring.spec.js @@ -340,6 +340,16 @@ describe('longestCommonSubstring', () => { expect(result).toEqual([]); }); + it('supports use cases related to issue #1', () => { + const result1 = longestCommonSubstring(['abc - 48h', 'abc - 108h', 'abc - 168h']); + const result2 = longestCommonSubstring(['abcTab', 'abcUab', 'abcTab']); + const result3 = longestCommonSubstring(['abcTde', 'abcUde', 'abcTde']); + + expect(result1).toEqual(['abc - ']); + expect(result2).toEqual(['abc']); + expect(result3).toEqual(['abc']); + }); + it('throws an error when given a boolean', () => { expect(() => longestCommonSubstring(true)).toThrow(); expect(() => longestCommonSubstring(false)).toThrow(); From 87a6784c78b99ac45baf16d398f28afecb37bae6 Mon Sep 17 00:00:00 2001 From: Arnaud Peloquin Date: Thu, 30 Apr 2020 10:07:14 +0200 Subject: [PATCH 4/4] Fix one typo in longest-common-substring.js --- src/longest-common-substring.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/longest-common-substring.js b/src/longest-common-substring.js index 9687d8f..8050e0c 100644 --- a/src/longest-common-substring.js +++ b/src/longest-common-substring.js @@ -5,7 +5,7 @@ * are concatenated with unique markers and their positions recorded in a * string index map. Iterating over the heights given in the longest common * prefix array, the string index map is used to lookup whet substring each - * suffix array enry belongs to. If k substrings are seen at the same height, + * suffix array entry belongs to. If k substrings are seen at the same height, * then a common substring across all given substrings has been found. * * Copyright (C) 2017 Kim Burgaard