'Input: `k \in [0 \ldots n-1]`, as for ``self`` only array ``p`` is used
Output: Representative of the class containing ``k``.
Returns the representative of `\sim` class containing ``k``, it also
makes some modification to array ``p`` of ``self`` to ease further
computations, described on Pg. 157 [1].
The information on classes under `\sim` is stored in array `p` of
``self`` argument, which will always satisfy the property:
`p[\alpha] \sim \alpha` and `p[\alpha]=\alpha \iff \alpha=rep(\alpha)`
`\forall \in [0 \ldots n-1]`.
So, for `\alpha \in [0 \ldots n-1]`, we find `rep(self, \alpha)` by
continually replacing `\alpha` by `p[\alpha]` until it becomes
constant (i.e satisfies `p[\alpha] = \alpha`):w
To increase the efficiency of later ``rep`` calculations, whenever we
find `rep(self, \alpha)=\beta`, we set
`p[\gamma] = \beta \forall \gamma \in p-chain` from `\alpha` to `\beta`
Notes
``rep`` routine is also described on Pg. 85-87 [1] in Atkinson\'s
algorithm, this results from the fact that ``coincidence`` routine
introduces functionality similar to that introduced by the
``minimal_block`` routine on Pg. 85-87 [1].
See also
coincidence, merge'

def rep(self, k):

    p = self.p
    lamda = k
    rho = p[lamda]
    while (rho != lamda):
        lamda = rho
        rho = p[lamda]
    mu = k
    rho = p[mu]
    while (rho != lamda):
        p[mu] = lamda
        mu = rho
        rho = p[mu]
    return lamda
