Skip to content

Commit 5c6a696

Browse files
committed
Merge pull request #35 from tayllan/master
Karp-Rabin String Matching
2 parents c660898 + da646f7 commit 5c6a696

File tree

3 files changed

+175
-1
lines changed

3 files changed

+175
-1
lines changed

algorithms/string/karp_rabin.js

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
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 rs = hashFunction(b);
48+
var newString = [];
49+
50+
for (var i = 0; i < bLength; i++) {
51+
newString.push(a.charAt(i));
52+
}
53+
54+
var rt = hashFunction(newString.join(''));
55+
56+
if (rs === rt && 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+
rt = reHash(
65+
bLength,
66+
rt,
67+
previousCharacter,
68+
nextCharacter
69+
);
70+
newString.shift();
71+
newString.push(nextCharacter);
72+
73+
if (rs === rt && checkEquality(b, newString.join(''))) {
74+
return true;
75+
}
76+
}
77+
78+
return false;
79+
}
80+
};
81+
82+
/**
83+
* Checks if 'a' is equal to 'b'
84+
*
85+
* @param String
86+
* @param String
87+
* @return Boolean
88+
*/
89+
var checkEquality = function (a, b) {
90+
var aLength = a.length;
91+
92+
for (var i = 0; i < aLength; i++) {
93+
if (a.charAt(i) !== b.charAt(i)) {
94+
return false;
95+
}
96+
}
97+
98+
return true;
99+
};
100+
101+
/**
102+
* Creates the hash representation of 'word'
103+
*
104+
* @param String
105+
* @return Number
106+
*/
107+
var hashFunction = function (word) {
108+
var hash = 0;
109+
var wordLength = word.length;
110+
111+
for (var i = 0, j = wordLength - 1; i < wordLength; i++, j--) {
112+
hash += word.charCodeAt(i) * Math.pow(base, j);
113+
}
114+
115+
return hash;
116+
};
117+
118+
/**
119+
* Recalculates the hash representation of a word so that it isn't
120+
* necessary to traverse the whole word again
121+
*
122+
* @param Number
123+
* @param Number
124+
* @param Character
125+
* @param Character
126+
* @return Number
127+
*/
128+
var reHash = function (length, hash, previousCharacter, nextCharacter) {
129+
hash -= previousCharacter.charCodeAt(0) * Math.pow(base, length - 1);
130+
hash *= base;
131+
hash += nextCharacter.charCodeAt(0);
132+
133+
return hash;
134+
};
135+
136+
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 karpRabin = 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(karpRabin('', ''), true);
31+
assert.equal(karpRabin('a', 'b'), false);
32+
assert.equal(karpRabin('b', 'a'), false);
33+
34+
// ' tes' is contained in 'super test'
35+
assert.equal(karpRabin('super test', ' tes'), true);
36+
});
37+
});

0 commit comments

Comments
 (0)