Skip to content

Commit

Permalink
Merge pull request #35 from tayllan/master
Browse files Browse the repository at this point in the history
Karp-Rabin String Matching
  • Loading branch information
felipernb committed Jun 1, 2014
2 parents c660898 + da646f7 commit 5c6a696
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 1 deletion.
136 changes: 136 additions & 0 deletions algorithms/string/karp_rabin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/**
* Copyright (C) 2014 Tayllan Búrigo
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
'use strict';

/**
* A prime number used to create
* the hash representation of a word
*
* Bigger the prime number,
* bigger the hash value
*/
var base = 997;

/**
* Calculates String Matching between two Strings
* Returns true if String 'b' is contained in String 'a'
*
* Average and Best Case Complexity: O(a.length + b.length)
* Worst Case Complexity: O(a.length * b.length)
*
* @param String
* @param String
* @return Boolean
*/
var karpRabin = function (a, b) {
var aLength = a.length;
var bLength = b.length;
var rs = hashFunction(b);
var newString = [];

for (var i = 0; i < bLength; i++) {
newString.push(a.charAt(i));
}

var rt = hashFunction(newString.join(''));

if (rs === rt && checkEquality(b, newString.join(''))) {
return true;
}
else {
for (i = 1; i < aLength; i++) {
var previousCharacter = newString[0];
var nextCharacter = a.charAt(i);

rt = reHash(
bLength,
rt,
previousCharacter,
nextCharacter
);
newString.shift();
newString.push(nextCharacter);

if (rs === rt && checkEquality(b, newString.join(''))) {
return true;
}
}

return false;
}
};

/**
* Checks if 'a' is equal to 'b'
*
* @param String
* @param String
* @return Boolean
*/
var checkEquality = function (a, b) {
var aLength = a.length;

for (var i = 0; i < aLength; i++) {
if (a.charAt(i) !== b.charAt(i)) {
return false;
}
}

return true;
};

/**
* Creates the hash representation of 'word'
*
* @param String
* @return Number
*/
var hashFunction = function (word) {
var hash = 0;
var wordLength = word.length;

for (var i = 0, j = wordLength - 1; i < wordLength; i++, j--) {
hash += word.charCodeAt(i) * Math.pow(base, j);
}

return hash;
};

/**
* Recalculates the hash representation of a word so that it isn't
* necessary to traverse the whole word again
*
* @param Number
* @param Number
* @param Character
* @param Character
* @return Number
*/
var reHash = function (length, hash, previousCharacter, nextCharacter) {
hash -= previousCharacter.charCodeAt(0) * Math.pow(base, length - 1);
hash *= base;
hash += nextCharacter.charCodeAt(0);

return hash;
};

module.exports = karpRabin;
3 changes: 2 additions & 1 deletion main.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ var lib = {
quicksort: require('./algorithms/sorting/quicksort')
},
String: {
editDistance: require('./algorithms/string/edit_distance')
editDistance: require('./algorithms/string/edit_distance'),
karpRabin: require('./algorithms/string/karp_rabin')
},
DataStructure: {
BST: require('./data_structures/bst'),
Expand Down
37 changes: 37 additions & 0 deletions test/algorithms/string/karp_rabin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Copyright (C) 2014 Tayllan Búrigo
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
'use strict';

var karpRabin = require('../../../algorithms/string/karp_rabin'),
assert = require('assert');

describe('Karp-Rabin', function () {
it('should verify if a string is contained in another string',
function () {
assert.equal(karpRabin('', ''), true);
assert.equal(karpRabin('a', 'b'), false);
assert.equal(karpRabin('b', 'a'), false);

// ' tes' is contained in 'super test'
assert.equal(karpRabin('super test', ' tes'), true);
});
});

0 comments on commit 5c6a696

Please sign in to comment.