using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CSEP521 { public class HashCounter { const uint P1 = 4294967291; // prime less than 2^32 const uint P2 = 65521; // prime less than 2^16 int B; int[] count; const uint CW_P = 2147483629; // prime less than 2^31 uint CW_A; uint CW_B; public HashCounter(int b, Random rand) { B = b; count = new int[B]; for (int i = 0; i < B; i++) count[i] = 0; CW_A = (uint) rand.Next(1, (int) CW_P); CW_B = (uint) rand.Next(1, (int) CW_P); } public void Count(string str) { count[Hash(str)]++; } public int LookupVal(string str) { return count[Hash(str)]; } // Compress the string to an unsigned int, and then use a C-W hash, then mod table size uint Hash(string str) { ulong val = HashString(str); ulong result = (val * CW_A + CW_B) % CW_P; return (uint)(result % (uint) B); } // evaluate a polynomial with the characters as coefficients uint HashString(string str) { ulong result = 0; ulong x = 1; for (int i = 0; i < str.Length; i++) { ulong c = (ulong) str[i]; result = (result + c * x) % P1; x = (x * P2) % P1; } return (uint) result; } public override string ToString() { return Algorithm.ArrayToString(count); } } }