I am doing an exercise from a Big Data course I'm taking on Coursera (this exercise is for experimenting with a big-data problem and is not for any credit or homework) , the assignment was described briefly:
Your task is to quickly find the number of pairs of sentences that are at the word-level edit distance at most 1. Two sentences S1 and S2 they are at edit distance 1 if S1 can be transformed to S2 by: adding, removing or substituting a single word.
I am then given a large txt file that contains about $10^6$ sentences.
The way I tried to attack this problem:
Observation $1$: If the length of two sentences is greater then $1$ then they are not at an edit distance $1$.
Observation $2$: Let $A_1,...,A_5$ be five consecutive words from a sentences and let $B_1,...,B_5$ be another five consecutive words chosen from different indexes (that is if we label the words of a sentence then $B_i$ and $A_j$ does not share an index.
- Five is a small arbitrary number I chose
I used something like a curried syntax to get a hashtable that keeps a 3-touple: $(X,Y,Z)$
Where I mapped each sentence as follows:
$X$ is the number of words the sentence have.
$Y$ is obtained by a hash function on the content of the words (I will soon describe this hash function)
$Z$ is a list of integers containing the index of the line in the document [the line number] that was mapped to $(X,Y)$
In C# this corresponds to an object of a type
Dictionary< int, Dictionary< int, List< int>>>
So I kept two Hashtables of the above form, where I took the first five words to hash and get $Y$ and words $6-10$ to hash and get another value of $Y$.
Then given a sentence - compute the two $Y$ values it would of gotten and look at buckets with length that differs at at most $1$ from this sentence length and share one $Y$ value this sentence.
Let me describe the hashing function I used to get $Y$ -
I took the $A_i$ (similarly with the $B_i$) and concatenated them
I looked at this string as a byte array (that is by the bits that takes to represent the numbers) I then applied a the SHA-1 hash function on it (there are no security reasons for this but I wanted something that hashes well)
I took the last $4$ bytes in the SHA-1 hash and I looked at it as a positive integer (by looking at the last $32$ bits and considering it as an integer then applying the absolute value function). Call this result $R$
- $Y= R\%p^{2}$
where $p$ was chosen as follows: I counted how many lines of a given length $l$ appear (say $n_l$), for lines of length $l$ I chose $p$ s.t $$\frac{n_l}{p^2}\leq 3$$
the following is a Histogram showing $n_l$ as a function of $l$
which should give some indication of the values chosen for $p$.
However - There are too many collisions - I get about $6$ elements in each bucket.
I took one example of such a bucket and I printed those sentences (I hoped they are similar so they would have a good reason to be mapped to the same bucket) by they are very different from one another. This is a printscreen of those sentences printed to the console.
Question: Why do I get a large number of collisions ?($6$ in average on $10^5$ buckets I considered where if I had even distribution I would expect $3$ from the choice of $p$, some buckets have a few tens of elements in them)
Could the problem be that I used modulo a square of a prime and not a prime ? is it that significant?