├── src └── rollinghash │ ├── CharacterHash.java │ ├── RabinKarpHash.java │ ├── CyclicHash.java │ └── Unit.java └── README.md /src/rollinghash/CharacterHash.java: -------------------------------------------------------------------------------- 1 | package rollinghash; 2 | 3 | import java.util.Random; 4 | 5 | 6 | // not to be used directly, see CyclicHash and RabinKarpHash instead 7 | public class CharacterHash { 8 | public int hashvalues[] = new int[1<<16]; 9 | 10 | public CharacterHash() { 11 | Random r = new Random(); 12 | for(int k = 0; k wordsize) { 9 | throw new IllegalArgumentException(); 10 | } 11 | 12 | } 13 | 14 | 15 | private int fastleftshiftn(int x) { 16 | return (x << n ) | (x >>> (wordsize-n)) ; 17 | } 18 | 19 | private static int fastleftshift1(int x) { 20 | return (x << 1 ) | (x >>> (wordsize-1)) ; 21 | } 22 | 23 | // add new character (useful to initiate the hasher) 24 | // to get a strongly universal hash value, you have to ignore the last or first (n-1) bits. 25 | public int eat(char c) { 26 | hashvalue = fastleftshift1(hashvalue); 27 | hashvalue ^= hasher.hashvalues[c]; 28 | return hashvalue; 29 | } 30 | 31 | // remove old character and add new one 32 | // to get a strongly universal hash value, you have to ignore the last or first (n-1) bits. 33 | public int update(char outchar, char inchar) { 34 | int z = fastleftshiftn(hasher.hashvalues[outchar]); 35 | hashvalue = fastleftshift1(hashvalue) ^ z ^ hasher.hashvalues[inchar]; 36 | return hashvalue; 37 | } 38 | 39 | // this is purely for testing purposes 40 | public static int nonRollingHash(CharSequence s) { 41 | int value = 0; 42 | for(int i = 0; i