Skip to content

Commit aa7be0a

Browse files
author
FSou1
committed
Add a simple hash algorithm
1 parent ef89822 commit aa7be0a

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Polynomial Rolling Hash
2+
3+
## Simple hash
4+
5+
**Time complexity**: `O(n)`, where n is the size of the string
6+
7+
## Rolling hash
8+
9+
**Time complexity**: `O(1)`.
10+
11+
## Reference
12+
13+
- [Youtube](https://www.youtube.com/watch?v=w6nuXg0BISo);
14+
- [Wikipedia](https://en.wikipedia.org/wiki/Rolling_hash);
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import {SimpleHasher} from '../simpleHash';
2+
3+
test.each([
4+
[null, 0],
5+
[undefined, 0],
6+
['', 0],
7+
['a', 97],
8+
[' a', 2263],
9+
['ab', 2351],
10+
['abc', 54722],
11+
['bcz', 66913],
12+
])('a hash representation of %p is %p', (word, hash) => {
13+
const hasher = new SimpleHasher();
14+
expect(hasher.hash(word)).toBe(hash);
15+
});
16+
17+
test.each([
18+
[97, 'a', 'b', 98],
19+
[2263, ' a', 'ab', 2351],
20+
[54722, 'abc', 'bcz', 66913],
21+
])('a rolled hash from %p of %p to %p is %p', (pHash, pWord, nWord, nHash) => {
22+
const hasher = new SimpleHasher();
23+
expect(hasher.roll(pHash, pWord, nWord)).toBe(nHash);
24+
});
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
const DEFAULT_BASE = 23;
2+
3+
/**
4+
* Simple polynomial hash
5+
*
6+
* @export
7+
* @class SimpleHasher
8+
*/
9+
export class SimpleHasher {
10+
base: number;
11+
12+
/**
13+
*Creates an instance of SimpleHasher
14+
* @param {*} [base=DEFAULT_BASE]
15+
* @memberof SimpleHasher
16+
*/
17+
constructor(base = DEFAULT_BASE) {
18+
this.base = base;
19+
}
20+
21+
/**
22+
* Creates a hash representation of the word
23+
*
24+
* @param {string} word
25+
* @return {number}
26+
* @memberof SimpleHasher
27+
*/
28+
hash(word: string): number {
29+
if (!word) {
30+
return 0;
31+
}
32+
33+
let hash = 0;
34+
35+
for (let charIndex = 0; charIndex < word.length; charIndex += 1) {
36+
hash += word.charCodeAt(charIndex) * (this.base ** charIndex);
37+
}
38+
39+
return hash;
40+
}
41+
42+
/**
43+
* Creates hash representation of the word based on
44+
* previous word (shifted by one character left) hash value
45+
*
46+
* @param {number} prevHash
47+
* @param {string} prevWord
48+
* @param {string} newWord
49+
* @return {number}
50+
* @memberof SimpleHasher
51+
*/
52+
roll(prevHash: number, prevWord: string, newWord: string): number {
53+
let hash = prevHash;
54+
55+
const prevValue = prevWord.charCodeAt(0);
56+
const newValue = newWord.charCodeAt(newWord.length - 1);
57+
58+
hash -= prevValue;
59+
hash /= this.base;
60+
hash += newValue * (this.base ** (newWord.length - 1));
61+
62+
return hash;
63+
}
64+
}

0 commit comments

Comments
 (0)