1pub fn duval(s: &str) -> Vec<String> {
2 let n: usize = s.len();
3 let mut i: usize = 0;
4 let mut factorization: Vec<String> = Vec::new();
5 while i < n {
6 let mut j: usize = i + 1;
7 let mut k: usize = i;
8 while j < n && s.as_bytes()[k] <= s.as_bytes()[j] {
9 if s.as_bytes()[k] < s.as_bytes()[j] {
10 k = i;
11 } else {
12 k += 1;
13 }
14 j += 1;
15 }
16 while i <= k {
17 factorization.push(s[i..j].to_string());
18 i += j - k;
19 }
20 }
21 factorization
22}
23
24pub fn min_rotation(s: &[u8]) -> usize {
25 let mut a: usize = 0;
26 let n: usize = s.len();
27 let mut b: usize = 0;
28 while b < n {
29 let mut i: usize = 0;
30 while a + i < n {
31 let sai: u8 = s[a + i];
32 let sbi: u8 = s[if b + i < n { b + i } else { b + i - n }];
33 if a + i == b || sai < sbi {
34 if i > 1 {
35 b += i - 1;
36 }
37 break;
38 }
39 if sai > sbi {
40 a = b;
41 break;
42 }
43 i += 1;
44 }
45 b += 1;
46 }
47 a
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53 use rand::Rng;
54 use rand::SeedableRng;
55
56 fn generate_random_string(length: usize, seed: u64) -> Vec<u8> {
57 const CHARACTERS: &[u8] = b"ACGT";
58 let mut rng: rand::rngs::StdRng = rand::rngs::StdRng::seed_from_u64(seed);
59
60 (0..length)
61 .map(|_| {
62 let idx: usize = rng.gen_range(0..CHARACTERS.len());
63 CHARACTERS[idx]
64 })
65 .collect()
66 }
67
68 fn min_rotation_naive(s: &[u8]) -> usize {
69 let n: usize = s.len();
70 let mut smin: Vec<u8> = s.to_vec();
71 let mut s_clone: Vec<u8> = s.to_vec();
72 let mut imin: usize = 0;
73 for i in 1..n {
74 s_clone.rotate_left(1);
75 if s_clone < smin {
76 smin = s_clone.clone();
77 imin = i;
78 }
79 }
80 imin
81 }
82
83 #[test]
84 fn test_min_rotation() {
85 const N_TESTS: u32 = 100000;
86 const N: usize = 10;
87
88 for test in 0..N_TESTS {
89 let s: Vec<u8> = generate_random_string(N, test as u64);
90 assert_eq!(min_rotation(&s), min_rotation_naive(&s));
91 }
92 }
93
94 #[test]
95 fn test_min_rotation_large() {
96 const N_TESTS: u32 = 10000;
97 const N: usize = 10000;
98
99 let mut strings: Vec<Vec<u8>> = vec![vec![b'A'; N]; N_TESTS as usize];
100 for test in 0..N_TESTS / 2 {
101 strings[test as usize] = generate_random_string(N, test as u64);
102 }
103
104 let mut sum = 0;
105 let start = std::time::Instant::now();
106 for s in strings {
107 sum += min_rotation(&s);
108 }
109 let duration = start.elapsed();
110 assert_ne!(sum, 0);
112 println!("Time: {:?}", duration);
113 }
114}