From d74f4394d358440a24bb00ae2c89e0cffd7d74a5 Mon Sep 17 00:00:00 2001 From: remes2000 Date: Sun, 2 Aug 2020 13:40:25 +0200 Subject: [PATCH] Implement longest common substring algorithm --- README.md | 1 + src/algorithms/string/index.js | 4 +- .../string/longest_common_substring.js | 40 ++++++++++++++++ .../string/testLongestCommonSubstring.js | 46 +++++++++++++++++++ 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 src/algorithms/string/longest_common_substring.js create mode 100644 test/algorithms/string/testLongestCommonSubstring.js diff --git a/README.md b/README.md index ce93985d..3d8f7129 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ Various Math algorithms: Various String algorithms: - [Levenshtein Distance](https://github.com/manrajgrover/algorithms-js/blob/master/src/algorithms/string/levenshtein_distance.js) +- [Longest Common Substring](https://github.com/manrajgrover/algorithms-js/blob/master/src/algorithms/string/longest_common_substring.js) #### Geometry Various Geometry algorithms: diff --git a/src/algorithms/string/index.js b/src/algorithms/string/index.js index ad535890..61fd95a8 100644 --- a/src/algorithms/string/index.js +++ b/src/algorithms/string/index.js @@ -1,5 +1,7 @@ const levenshteindistance = require('./levenshtein_distance'); +const longestcommonsubstring = require('./longest_common_substring'); module.exports = { - levenshteindistance + levenshteindistance, + longestcommonsubstring }; diff --git a/src/algorithms/string/longest_common_substring.js b/src/algorithms/string/longest_common_substring.js new file mode 100644 index 00000000..c360bcd5 --- /dev/null +++ b/src/algorithms/string/longest_common_substring.js @@ -0,0 +1,40 @@ +/** + * Returns Longest Common Substring of two strings + * @param {String} firstWord First string + * @param {String} secondWord Second string + * @return {String} One of the possbile longest common substring for given inputs + */ +function longestcommonsubstring(firstWord = '', secondWord = '') { + const firstWordSize = firstWord.length; + const secondWordSize = secondWord.length; + const table = [...Array(firstWordSize + 1)].map(() => Array(secondWordSize + 1)); + let maxSubstringLength = 0; + let maxSubstringRow = 0; + let maxSubstringCol = 0; + for (let i = 0; i <= firstWordSize; i += 1) { + for (let j = 0; j <= secondWordSize; j += 1) { + if (i === 0 || j === 0) { + table[i][j] = 0; + } else if (firstWord.charAt(i - 1) === secondWord.charAt(j - 1)) { + table[i][j] = table[i - 1][j - 1] + 1; + if (table[i][j] > maxSubstringLength) { + maxSubstringLength = table[i][j]; + maxSubstringRow = i; + maxSubstringCol = j; + } + } else { + table[i][j] = 0; + } + } + } + + let result = ''; + while (table[maxSubstringRow][maxSubstringCol] !== 0) { + result = firstWord.charAt(maxSubstringRow - 1) + result; + maxSubstringRow -= 1; + maxSubstringCol -= 1; + } + return result; +} + +module.exports = longestcommonsubstring; diff --git a/test/algorithms/string/testLongestCommonSubstring.js b/test/algorithms/string/testLongestCommonSubstring.js new file mode 100644 index 00000000..47a0c7a9 --- /dev/null +++ b/test/algorithms/string/testLongestCommonSubstring.js @@ -0,0 +1,46 @@ +/* eslint-env mocha */ +const longestcommonsubstring = require('../../../src').algorithms.string.longestcommonsubstring; +const assert = require('assert'); + +describe('Longest Common Substring', () => { + it('should find abcd for xyzabcd and abcdxyz', () => { + const stringA = 'xyzabcd'; + const stringB = 'abcdxyz'; + + const result = longestcommonsubstring(stringA, stringB); + assert.equal(result, 'abcd'); + }); + + it('should find Geeks for GeeksforGeeks and GeeksQuiz', () => { + const stringA = 'GeeksForGeeks'; + const stringB = 'GeeksQuiz'; + + const result = longestcommonsubstring(stringA, stringB); + assert.equal(result, 'Geeks'); + }); + + it('should return empty string when one or both of inputs is empty', () => { + const resultOne = longestcommonsubstring('abcdef', ''); + assert.equal(resultOne, ''); + const resultTwo = longestcommonsubstring('', 'abcasds'); + assert.equal(resultTwo, ''); + const resultThree = longestcommonsubstring('', ''); + assert.equal(resultThree, ''); + }); + + it('should return empty string for letter and aggghhhww', () => { + const stringA = 'letter'; + const stringB = 'aggghhhww'; + + const result = longestcommonsubstring(stringA, stringB); + assert.equal(result, ''); + }); + + it('should return a for xysysysyysahhfghf and aaaaaa', () => { + const stringA = 'xysysysyysahhfghf'; + const stringB = 'aaaaaa'; + + const result = longestcommonsubstring(stringA, stringB); + assert.equal(result, 'a'); + }); +});