Repository navigation
Expand file tree
/
Copy pathBoothsAlgorithm.java
More file actions
69 lines (61 loc) · 2.18 KB
/
Copy pathBoothsAlgorithm.java
File metadata and controls
69 lines (61 loc) · 2.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package com.thealgorithms.strings;
/**
* Finds the lexicographically smallest cyclic rotation of a string using
* Booth's algorithm.
*
* <p>The algorithm compares candidate rotations without materializing them,
* running in O(n) time and O(1) auxiliary space.</p>
*
* @see <a href="https://en.wikipedia.org/wiki/Lexicographically_minimal_string_rotation">
* Lexicographically minimal string rotation</a>
*/
public final class BoothsAlgorithm {
private BoothsAlgorithm() {
}
/**
* Returns the starting index of the lexicographically smallest cyclic
* rotation of {@code input}. If several rotations are equal and minimal,
* the algorithm returns the smallest starting index among them.
*
* <p>For example, the smallest rotation of {@code "baca"} is
* {@code "abac"}, which starts at index {@code 3}.</p>
*
* @param input the string whose minimal cyclic rotation is sought
* @return the starting index of the minimal rotation, or {@code 0} for an
* empty string
* @throws IllegalArgumentException if {@code input} is {@code null}
*/
public static int minimalRotationIndex(String input) {
if (input == null) {
throw new IllegalArgumentException("Input string must not be null");
}
int length = input.length();
if (length == 0) {
return 0;
}
int first = 0;
int second = 1;
int offset = 0;
while (first < length && second < length && offset < length) {
char firstChar = input.charAt((first + offset) % length);
char secondChar = input.charAt((second + offset) % length);
if (firstChar == secondChar) {
offset++;
continue;
}
if (firstChar > secondChar) {
first += offset + 1;
if (first <= second) {
first = second + 1;
}
} else {
second += offset + 1;
if (second <= first) {
second = first + 1;
}
}
offset = 0;
}
return Math.min(first, second);
}
}