dsalgo 0.3.10

A package for Datastructures and Algorithms.
Documentation
pub fn suffix_array<T: Ord>(a: &[T]) -> Vec<usize> {
    let n = a.len();

    fn counting_argsort(a: &Vec<usize>) -> Vec<usize> {
        let n = a.len();

        let mut arg = vec![0; n + 2];

        for &x in a.iter() {
            arg[x + 1] += 1;
        }

        let mut key = vec![0; n];

        for i in 0..n {
            arg[i + 1] += arg[i];
        }

        for (i, &x) in a.iter().enumerate() {
            key[arg[x]] = i;

            arg[x] += 1;
        }

        key
    }

    let mut v = Vec::with_capacity(n);

    for x in a.iter() {
        v.push(x);
    }

    v.sort_unstable();

    v.dedup();

    let mut a: Vec<_> =
        a.iter().map(|x| v.binary_search(&x).unwrap() + 1).collect();

    let mut k = 1usize;

    loop {
        let key_1 =
            (0..n).map(|i| if i + k < n { a[i + k] } else { 0 }).collect();

        let sa_1 = counting_argsort(&key_1);

        let key_0 = sa_1.iter().map(|&i| a[i]).collect();

        let sa_0 = counting_argsort(&key_0);

        let sa: Vec<_> = sa_0.iter().map(|&i| sa_1[i]).collect();

        let key: Vec<_> = sa_0
            .iter()
            .zip(sa.iter())
            .map(|(&i, &j)| key_0[i] << 30 | key_1[j])
            .collect();

        k <<= 1;

        if k >= n {
            return sa;
        }

        let mut rank = 0;

        let mut prev = 0;

        for (&sa, &key) in sa.iter().zip(key.iter()) {
            if key > prev {
                rank += 1;

                prev = key;
            }

            a[sa] = rank;
        }

        if rank == n {
            return sa;
        }
    }
}

#[cfg(test)]

mod tests {

    use super::*;

    #[test]

    fn test() {
        let cases = vec![
            (
                vec![1, 1, 0, 0, 3, 3, 0, 0, 3, 3, 0, 0, 2, 2, 0, 0],
                vec![15, 14, 10, 6, 2, 11, 7, 3, 1, 0, 13, 12, 9, 5, 8, 4],
            ),
            (
                vec![1, 0, 3, 3, 0, 3, 3, 0, 2, 2, 0],
                vec![10, 7, 4, 1, 0, 9, 8, 6, 3, 5, 2],
            ),
        ];

        for (s, ans) in cases {
            assert_eq!(suffix_array(&s), ans);
        }
    }
}