Skip to content
This repository was archived by the owner on Dec 3, 2023. It is now read-only.

Commit 12a7da2

Browse files
committed
Fixed bug in Knuth Morris Pratt algorithm. Randomized Knuth Morris Pratt algorithm tests.
1 parent 0d347cf commit 12a7da2

5 files changed

+47
-63
lines changed

algorithms/es/knuthMorrisPrattStringMatch.js

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,21 @@
77

88
'use strict'
99

10-
let input = null
11-
let pattern = null
12-
let longestSuffixPrefix = null
13-
14-
const knuthMorrisPrattStringMatch = (userInput = null, stringPattern = null) => {
15-
if (userInput === null || stringPattern === null) return null
16-
input = userInput
17-
pattern = stringPattern
18-
if (pattern.length > input.length || pattern.length === 0) return null
19-
longestSuffixPrefix = [0]
20-
for (let i = 1, j = updateLongestSuffixPrefix(longestSuffixPrefix[i - 1], i); i < pattern.length; i++, j = updateLongestSuffixPrefix(longestSuffixPrefix[i - 1], i)) longestSuffixPrefix.push(j)
21-
for (let i = 0, j = setLongestSuffixPrefix(0, i); i < input.length; i++, j = setLongestSuffixPrefix(j, i)) if (input.charAt(i) === pattern.charAt(j++) && j === pattern.length) return i - (j - 1)
10+
const knuthMorrisPrattStringMatch = (input = null, pattern = null) => {
11+
if (input === null || input.length === 0 || pattern === null || pattern.length === 0) return null
12+
let lsp = [0]
13+
for (let i = 1, j = lsp[i - 1]; i < pattern.length; i++, j = lsp[i - 1]) {
14+
while (j > 0 && pattern.charAt(i) !== pattern.charAt(j)) j = lsp[j - 1]
15+
if (pattern.charAt(i) === pattern.charAt(j)) j++
16+
lsp.push(j)
17+
}
18+
for (let i = 0, j = 0; i < input.length; i++) {
19+
while (j > 0 && input.charAt(i) !== pattern.charAt(j)) j = lsp[j - 1]
20+
if (input.charAt(i) === pattern.charAt(j) && ++j === pattern.length) return i - (j - 1)
21+
}
2222
return null
2323
}
2424

25-
const updateLongestSuffixPrefix = (j, i) => {
26-
while (j > 0 && pattern.charAt(i) !== pattern.charAt(j)) j = longestSuffixPrefix[j - 1]
27-
if (pattern.charAt(i) === pattern.charAt(j)) j++
28-
return j
29-
}
30-
31-
const setLongestSuffixPrefix = (j, i) => {
32-
while (j > 0 && input.charAt(i) !== pattern.charAt(j)) j = longestSuffixPrefix[j - 1]
33-
return j
34-
}
35-
3625
export default knuthMorrisPrattStringMatch
3726

3827
/*

algorithms/es5/knuthMorrisPrattStringMatch.js

Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,37 +16,24 @@
1616
Object.defineProperty(exports, '__esModule', {
1717
value: true
1818
})
19-
var input = null
20-
var pattern = null
21-
var longestSuffixPrefix = null
22-
2319
var knuthMorrisPrattStringMatch = function knuthMorrisPrattStringMatch () {
24-
var userInput = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null
25-
var stringPattern = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null
26-
27-
if (userInput === null || stringPattern === null) return null
28-
input = userInput
29-
pattern = stringPattern
30-
if (pattern.length > input.length || pattern.length === 0) return null
31-
longestSuffixPrefix = [0]
32-
for (var i = 1, j = updateLongestSuffixPrefix(longestSuffixPrefix[i - 1], i); i < pattern.length; i++, j = updateLongestSuffixPrefix(longestSuffixPrefix[i - 1], i)) {
33-
longestSuffixPrefix.push(j)
34-
} for (var _i = 0, _j = setLongestSuffixPrefix(0, _i); _i < input.length; _i++, _j = setLongestSuffixPrefix(_j, _i)) {
35-
if (input.charAt(_i) === pattern.charAt(_j++) && _j === pattern.length) return _i - (_j - 1)
36-
} return null
37-
}
20+
var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null
21+
var pattern = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null
3822

39-
var updateLongestSuffixPrefix = function updateLongestSuffixPrefix (j, i) {
40-
while (j > 0 && pattern.charAt(i) !== pattern.charAt(j)) {
41-
j = longestSuffixPrefix[j - 1]
42-
} if (pattern.charAt(i) === pattern.charAt(j)) j++
43-
return j
44-
}
45-
46-
var setLongestSuffixPrefix = function setLongestSuffixPrefix (j, i) {
47-
while (j > 0 && input.charAt(i) !== pattern.charAt(j)) {
48-
j = longestSuffixPrefix[j - 1]
49-
} return j
23+
if (input === null || input.length === 0 || pattern === null || pattern.length === 0) return null
24+
var lsp = [0]
25+
for (var i = 1, j = lsp[i - 1]; i < pattern.length; i++, j = lsp[i - 1]) {
26+
while (j > 0 && pattern.charAt(i) !== pattern.charAt(j)) {
27+
j = lsp[j - 1]
28+
} if (pattern.charAt(i) === pattern.charAt(j)) j++
29+
lsp.push(j)
30+
}
31+
for (var _i = 0, _j = 0; _i < input.length; _i++) {
32+
while (_j > 0 && input.charAt(_i) !== pattern.charAt(_j)) {
33+
_j = lsp[_j - 1]
34+
} if (input.charAt(_i) === pattern.charAt(_j) && ++_j === pattern.length) return _i - (_j - 1)
35+
}
36+
return null
5037
}
5138

5239
exports.default = knuthMorrisPrattStringMatch

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"nyc": "^11.4.1",
4545
"replace": "^0.3.0",
4646
"shx": "^0.2.2",
47-
"standard": "^10.0.3"
47+
"standard": "^10.0.3",
48+
"uuid": "^3.2.1"
4849
}
4950
}

test/es/knuthMorrisPrattStringMatchTests.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
// NPM Modules
44
import chai from 'chai'
5+
import uuid from 'uuid/v4'
56

67
// Algorithm
78
import { knuthMorrisPrattStringMatch } from '../../es'
@@ -11,11 +12,12 @@ const expect = chai.expect
1112
// Test
1213
describe('Knuth-Morris-Pratt String Match Algorithm: knuthMorrisPrattStringMatch(input, pattern)', () => {
1314
it('Should return the proper index value of the pattern in the input string when it exists in the input string.', () => {
14-
expect(knuthMorrisPrattStringMatch('test', 'est')).to.eql(1)
15-
expect(knuthMorrisPrattStringMatch('tafsesrt', 'esrt')).to.eql(4)
16-
expect(knuthMorrisPrattStringMatch('testtest', 'stt')).to.eql(2)
17-
expect(knuthMorrisPrattStringMatch('testtest', 'test')).to.eql(0)
18-
expect(knuthMorrisPrattStringMatch('testtest', 'ttest')).to.eql(3)
15+
for (let i = 0; i < 10000; i++) {
16+
let string = uuid()
17+
let index = Math.floor(Math.random() * (string.length / 2))
18+
let pattern = string.substr(index, Math.floor(Math.random() * string.length + 2))
19+
expect(knuthMorrisPrattStringMatch(string, pattern)).to.eql(string.indexOf(pattern))
20+
}
1921
})
2022
it('Should return null when the given pattern does not exist inside the input string.', () => {
2123
expect(knuthMorrisPrattStringMatch('test', 'xyz')).to.eql(null)

test/es5/knuthMorrisPrattStringMatchTests.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ var _chai = require('chai')
44

55
var _chai2 = _interopRequireDefault(_chai)
66

7+
var _v = require('uuid/v4')
8+
9+
var _v2 = _interopRequireDefault(_v)
10+
711
var _es = require('../../es5')
812

913
function _interopRequireDefault (obj) { return obj && obj.__esModule ? obj : { default: obj } }
@@ -12,11 +16,12 @@ var expect = _chai2.default.expect
1216

1317
describe('Knuth-Morris-Pratt String Match ES5 Algorithm: knuthMorrisPrattStringMatch(input, pattern)', function () {
1418
it('Should return the proper index value of the pattern in the input string when it exists in the input string.', function () {
15-
expect((0, _es.knuthMorrisPrattStringMatch)('test', 'est')).to.eql(1)
16-
expect((0, _es.knuthMorrisPrattStringMatch)('tafsesrt', 'esrt')).to.eql(4)
17-
expect((0, _es.knuthMorrisPrattStringMatch)('testtest', 'stt')).to.eql(2)
18-
expect((0, _es.knuthMorrisPrattStringMatch)('testtest', 'test')).to.eql(0)
19-
expect((0, _es.knuthMorrisPrattStringMatch)('testtest', 'ttest')).to.eql(3)
19+
for (var i = 0; i < 10000; i++) {
20+
var string = (0, _v2.default)()
21+
var index = Math.floor(Math.random() * (string.length / 2))
22+
var pattern = string.substr(index, Math.floor(Math.random() * string.length + 2))
23+
expect((0, _es.knuthMorrisPrattStringMatch)(string, pattern)).to.eql(string.indexOf(pattern))
24+
}
2025
})
2126
it('Should return null when the given pattern does not exist inside the input string.', function () {
2227
expect((0, _es.knuthMorrisPrattStringMatch)('test', 'xyz')).to.eql(null)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy