From 9e5deb66951fc37f1ae340e1566a412598516e29 Mon Sep 17 00:00:00 2001 From: Hari Venugopalan Date: Wed, 20 Jun 2018 18:33:22 -0700 Subject: [PATCH 1/3] Implemented Z algorithm --- .../string/z-algorithm/zAlgorithm.js | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/algorithms/string/z-algorithm/zAlgorithm.js diff --git a/src/algorithms/string/z-algorithm/zAlgorithm.js b/src/algorithms/string/z-algorithm/zAlgorithm.js new file mode 100644 index 0000000000..b0a8480325 --- /dev/null +++ b/src/algorithms/string/z-algorithm/zAlgorithm.js @@ -0,0 +1,51 @@ +/** + * @param {string} word + * @param {string} text + * @return {number[]} + */ + +function buildZArray(word, text) { + let zString = word+"$+"text; + let zArray = new Array(zString.length); + let left = 0, right = 0, k = 0; + + for (let i = 1; i < zString.length; i++) { + if (i > right) { + left = right = 0; + while ( right Date: Wed, 20 Jun 2018 19:18:37 -0700 Subject: [PATCH 2/3] Fixed bugs in implementation and added tests --- .../z-algorithm/__test__/zAlgorithm.test.js | 12 +++++ .../string/z-algorithm/zAlgorithm.js | 52 +++++++++++-------- 2 files changed, 41 insertions(+), 23 deletions(-) create mode 100644 src/algorithms/string/z-algorithm/__test__/zAlgorithm.test.js diff --git a/src/algorithms/string/z-algorithm/__test__/zAlgorithm.test.js b/src/algorithms/string/z-algorithm/__test__/zAlgorithm.test.js new file mode 100644 index 0000000000..d58ff75bc9 --- /dev/null +++ b/src/algorithms/string/z-algorithm/__test__/zAlgorithm.test.js @@ -0,0 +1,12 @@ +import zAlgorithm from '../zAlgorithm'; + +describe('zAlgorithm', () => { + it('should find word position in given text', () => { + expect(zAlgorithm('abcbcglx', 'abca')).toBe(-1); + expect(zAlgorithm('abcbcglx', 'bcgl')).toBe(3); + expect(zAlgorithm('abcxabcdabxabcdabcdabcy', 'abcdabcy')).toBe(15); + expect(zAlgorithm('abcxabcdabxabcdabcdabcy', 'abcdabca')).toBe(-1); + expect(zAlgorithm('abcxabcdabxaabcdabcabcdabcdabcy', 'abcdabca')).toBe(12); + expect(zAlgorithm('abcxabcdabxaabaabaaaabcdabcdabcy', 'aabaabaaa')).toBe(11); + }); +}); diff --git a/src/algorithms/string/z-algorithm/zAlgorithm.js b/src/algorithms/string/z-algorithm/zAlgorithm.js index b0a8480325..f93318ce43 100644 --- a/src/algorithms/string/z-algorithm/zAlgorithm.js +++ b/src/algorithms/string/z-algorithm/zAlgorithm.js @@ -5,47 +5,53 @@ */ function buildZArray(word, text) { - let zString = word+"$+"text; - let zArray = new Array(zString.length); - let left = 0, right = 0, k = 0; + const zString = `${word}$${text}`; + const zArray = new Array(zString.length); + let left = 0; + let right = 0; + let k = 0; - for (let i = 1; i < zString.length; i++) { + for (let i = 1; i < zString.length; i += 1) { if (i > right) { - left = right = 0; - while ( right Date: Wed, 20 Jun 2018 19:36:38 -0700 Subject: [PATCH 3/3] Added README explaining z algorithm --- src/algorithms/string/z-algorithm/README.md | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/algorithms/string/z-algorithm/README.md diff --git a/src/algorithms/string/z-algorithm/README.md b/src/algorithms/string/z-algorithm/README.md new file mode 100644 index 0000000000..733ebf5cd1 --- /dev/null +++ b/src/algorithms/string/z-algorithm/README.md @@ -0,0 +1,27 @@ +# Z-algorithm + +The Z-algorithm finds occurrences of a "word" `W` +within a main "text string" `T` in linear time. + +Given a string `S` of length `n`, the algorithm produces +an array, `Z` where `Z[i]` represents the ongest substring +starting from `S[i]` which is also a prefix of `S`. Finding +`Z` for the string obtained by concatenating the word, `W` +with a nonce character, say `$` followed by the text, `T`, +helps with pattern matching, for if there is some index `i` +such that `Z[i]` equals the pattern length, then the pattern +must be present at that point. + +While the `Z` array can be computed with two nested loops, the +following strategy shows how to obtain it in linear time, based +on the idea that as we iterate over the letters in the string +(index `i` from `1` to `n - 1`), we maintain an interval `[L, R]` +which is the interval with maximum `R` such that `1 ≤ L ≤ i ≤ R` +and `S[L...R]` is a prefix that is also a substring (if no such +interval exists, just let `L = R =  - 1`). For `i = 1`, we can +simply compute `L` and `R` by comparing `S[0...]` to `S[1...]`. + +## Complexity + +- **Time:** `O(|W| + |T|)` +- **Space:** `O(|W|)` \ No newline at end of file