From 91935dbf4eeca9b9516760482694c2723c21a896 Mon Sep 17 00:00:00 2001 From: Vedant Hemraj Kapgate Date: Sun, 11 Oct 2026 17:16:37 +0530 Subject: [PATCH 1/3] Add Booth's algorithm for minimal string rotation --- .../strings/BoothsAlgorithm.java | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/main/java/com/thealgorithms/strings/BoothsAlgorithm.java diff --git a/src/main/java/com/thealgorithms/strings/BoothsAlgorithm.java b/src/main/java/com/thealgorithms/strings/BoothsAlgorithm.java new file mode 100644 index 000000000000..1de490ca9936 --- /dev/null +++ b/src/main/java/com/thealgorithms/strings/BoothsAlgorithm.java @@ -0,0 +1,70 @@ +package com.thealgorithms.strings; + +/** + * Finds the lexicographically smallest cyclic rotation of a string using + * Booth's algorithm. + * + *

The algorithm compares candidate rotations without materializing them, + * running in O(n) time and O(1) auxiliary space.

+ * + * @see + * Lexicographically minimal string rotation + */ +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. + * + *

For example, the smallest rotation of {@code "baca"} is + * {@code "abac"}, which starts at index {@code 3}.

+ * + * @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; + } + + String doubled = input + input; + int first = 0; + int second = 1; + int offset = 0; + + while (first < length && second < length && offset < length) { + char firstChar = doubled.charAt(first + offset); + char secondChar = doubled.charAt(second + offset); + + 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); + } +} From 142adada6b1dacb83215bca8ed24c80fb3b78ff6 Mon Sep 17 00:00:00 2001 From: Vedant Hemraj Kapgate Date: Sun, 11 Oct 2026 17:16:40 +0530 Subject: [PATCH 2/3] Add tests for Booth's minimal rotation algorithm --- .../strings/BoothsAlgorithmTest.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/test/java/com/thealgorithms/strings/BoothsAlgorithmTest.java diff --git a/src/test/java/com/thealgorithms/strings/BoothsAlgorithmTest.java b/src/test/java/com/thealgorithms/strings/BoothsAlgorithmTest.java new file mode 100644 index 000000000000..19ff58eb0988 --- /dev/null +++ b/src/test/java/com/thealgorithms/strings/BoothsAlgorithmTest.java @@ -0,0 +1,45 @@ +package com.thealgorithms.strings; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; + +public class BoothsAlgorithmTest { + + @Test + public void testMinimalRotationIndexForExample() { + assertEquals(3, BoothsAlgorithm.minimalRotationIndex("baca")); + } + + @Test + public void testEmptyString() { + assertEquals(0, BoothsAlgorithm.minimalRotationIndex("")); + } + + @Test + public void testSingleCharacter() { + assertEquals(0, BoothsAlgorithm.minimalRotationIndex("x")); + } + + @Test + public void testRepeatedCharacters() { + assertEquals(0, BoothsAlgorithm.minimalRotationIndex("aaaaa")); + } + + @Test + public void testPeriodicString() { + assertEquals(1, BoothsAlgorithm.minimalRotationIndex("baba")); + assertEquals(1, BoothsAlgorithm.minimalRotationIndex("cabcab")); + } + + @Test + public void testStringAlreadyHasMinimalRotationAtStart() { + assertEquals(0, BoothsAlgorithm.minimalRotationIndex("abc")); + } + + @Test + public void testNullInput() { + assertThrows(IllegalArgumentException.class, () -> BoothsAlgorithm.minimalRotationIndex(null)); + } +} From f33ad1aff9209eff69ea4723357a59d78c432024 Mon Sep 17 00:00:00 2001 From: Vedant Hemraj Kapgate Date: Sun, 11 Oct 2026 17:17:04 +0530 Subject: [PATCH 3/3] Use constant-space comparisons in Booth's algorithm --- src/main/java/com/thealgorithms/strings/BoothsAlgorithm.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/thealgorithms/strings/BoothsAlgorithm.java b/src/main/java/com/thealgorithms/strings/BoothsAlgorithm.java index 1de490ca9936..01c2f67a8569 100644 --- a/src/main/java/com/thealgorithms/strings/BoothsAlgorithm.java +++ b/src/main/java/com/thealgorithms/strings/BoothsAlgorithm.java @@ -37,14 +37,13 @@ public static int minimalRotationIndex(String input) { return 0; } - String doubled = input + input; int first = 0; int second = 1; int offset = 0; while (first < length && second < length && offset < length) { - char firstChar = doubled.charAt(first + offset); - char secondChar = doubled.charAt(second + offset); + char firstChar = input.charAt((first + offset) % length); + char secondChar = input.charAt((second + offset) % length); if (firstChar == secondChar) { offset++;