Skip to content

Commit 9878882

Browse files
committed
Karp-Rabin String Matching
1 parent c660898 commit 9878882

File tree

3 files changed

+170
-1
lines changed

3 files changed

+170
-1
lines changed

algorithms/string/karp_rabin.js

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/**
2+
* Copyright (C) 2014 Tayllan Búrigo
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to
6+
* deal in the Software without restriction, including without limitation the
7+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8+
* sell copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20+
* IN THE SOFTWARE.
21+
*/
22+
'use strict';
23+
24+
/**
25+
* A prime number used to create
26+
* the hash representation of a word
27+
*
28+
* Bigger the prime number,
29+
* bigger the hash value
30+
*/
31+
var base = 997;
32+
33+
/**
34+
* Calculates String Matching between two Strings
35+
* Returns true if String 'b' is contained in String 'a'
36+
*
37+
* Average and Best Case Complexity: O(a.length + b.length)
38+
* Worst Case Complexity: O(a.length * b.length)
39+
*
40+
* @param String
41+
* @param String
42+
* @return Boolean
43+
*/
44+
var karpRabin = function (a, b) {
45+
var aLength = a.length;
46+
var bLength = b.length;
47+
var hashValue = hashFunction(b);
48+
var newString = [];
49+
50+
for (var i = 0; i < bLength; i++) {
51+
newString.push(a.charAt(i));
52+
}
53+
54+
var newStringHashValue = hashFunction(newString.join(''));
55+
56+
if (hashValue === newStringHashValue && checkEquality(b, newString.join(''))) {
57+
return true;
58+
}
59+
else {
60+
for (i = 1; i < aLength; i++) {
61+
var previousCharacter = newString[0];
62+
var nextCharacter = a.charAt(i);
63+
64+
newStringHashValue = reHash(b.length, newStringHashValue, previousCharacter, nextCharacter);
65+
newString.shift();
66+
newString.push(nextCharacter);
67+
68+
if (hashValue === newStringHashValue && checkEquality(b, newString.join(''))) {
69+
return true;
70+
}
71+
}
72+
73+
return false;
74+
}
75+
};
76+
77+
/**
78+
* Checks if 'a' is equal to 'b'
79+
*
80+
* @param String
81+
* @param String
82+
* @return Boolean
83+
*/
84+
var checkEquality = function (a, b) {
85+
var aLength = a.length;
86+
87+
for (var i = 0; i < aLength; i++) {
88+
if (a.charAt(i) !== b.charAt(i)) {
89+
return false;
90+
}
91+
}
92+
93+
return true;
94+
};
95+
96+
/**
97+
* Creates the hash representation of 'word'
98+
*
99+
* @param String
100+
* @return Number
101+
*/
102+
var hashFunction = function (word) {
103+
var hash = 0;
104+
var wordLength = word.length;
105+
106+
for (var i = 0, j = wordLength - 1; i < wordLength; i++, j--) {
107+
hash += word.charCodeAt(i) * Math.pow(base, j);
108+
}
109+
110+
return hash;
111+
};
112+
113+
/**
114+
* Recalculates the hash representation of a word so that it isn't
115+
* necessary to traverse the whole word again
116+
*
117+
* @param Number
118+
* @param Number
119+
* @param Character
120+
* @param Character
121+
* @return Number
122+
*/
123+
var reHash = function (length, hash, previousCharacter, nextCharacter) {
124+
hash -= previousCharacter.charCodeAt(0) * Math.pow(base, length - 1);
125+
hash *= base;
126+
hash += nextCharacter.charCodeAt(0);
127+
128+
return hash;
129+
};
130+
131+
module.exports = karpRabin;

main.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ var lib = {
4242
quicksort: require('./algorithms/sorting/quicksort')
4343
},
4444
String: {
45-
editDistance: require('./algorithms/string/edit_distance')
45+
editDistance: require('./algorithms/string/edit_distance'),
46+
karpRabin: require('./algorithms/string/karp_rabin')
4647
},
4748
DataStructure: {
4849
BST: require('./data_structures/bst'),

test/algorithms/string/karp_rabin.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* Copyright (C) 2014 Tayllan Búrigo
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to
6+
* deal in the Software without restriction, including without limitation the
7+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8+
* sell copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20+
* IN THE SOFTWARE.
21+
*/
22+
'use strict';
23+
24+
var karp_rabin = require('../../../algorithms/string/karp_rabin'),
25+
assert = require('assert');
26+
27+
describe('Karp-Rabin', function () {
28+
it('should verify if a string is contained in another string',
29+
function () {
30+
assert.equal(karp_rabin('', ''), true);
31+
assert.equal(karp_rabin('a', 'b'), false);
32+
assert.equal(karp_rabin('b', 'a'), false);
33+
34+
// ' tes' is contained in 'super test'
35+
assert.equal(karp_rabin('super test', ' tes'), true);
36+
});
37+
});

0 commit comments

Comments
 (0)