CSES Solutions - Minimal Rotation
Last Updated :
15 Apr, 2024
A rotation of a string can be generated by moving characters one after another from beginning to end. For example, the rotations of acab are acab, caba, abac, and baca.
Your task is to determine the lexicographically minimal rotation of a string.
Examples:
Input: s = "acab"
Output: abac
Explanation: All possible rotations are: "acab", "caba", "abac" and "baca". The lexicographically smallest string is "abac".
Input: s = "GeeksforGeeks"
Output: GeeksGeeksfor
Explanation: Out of possible rotations "GeeksGeeksfor" is lexicographically smallest.
Approach: To solve the problem, follow the below idea:
The idea is to uses Booth’s algorithm, which is a well-known algorithm for this problem. The main idea of Booth’s algorithm is to construct a failure function (similar to the one used in the KMP pattern matching algorithm) for the given string concatenated with itself. This failure function is used to efficiently compare prefixes of the string to find the smallest rotation.
Let's break our idea in some steps:
- Concatenate the string to itself: This allows us to easily handle the wrap-around nature of rotations without having to use modular arithmetic.
- Initialize the failure function and the minimum rotation index: The failure function f is an array that stores the length of the longest proper suffix of the substring S[0..j] which is also a proper prefix of S. The minimum rotation index k keeps track of the starting index of the smallest rotation found so far.
- Iterate over the concatenated string: For each character S[j] in the string, we compare it with the character at the corresponding position in the current smallest rotation. If S[j] is smaller, we update the minimum rotation index k.
- Update the failure function: The failure function is updated based on whether S[j] is equal to S[k + f[j - k - 1] + 1] . If they are equal, f[j - k] is set to f[j - k - 1] + 1. Otherwise, f[j - k] is set to -1.
- Return the minimum rotation index: After iterating over the entire string, the minimum rotation index k gives the starting index of the lexicographically smallest rotation.
Step-by-step algorithm:
- Create a function findMinRotation() takes a string s as input and finds the lexicographically minimal rotation of the string.
- It concatenates the input string with itself to avoid modular arithmetic.
- Create a failure function vector with -1 values and sets the initial minimum rotation index to 0.
- Iterates over the concatenated string to find the lexicographically minimal rotation.
- Updates the failure function and minimum rotation index based on comparisons.
- Returns the index of the lexicographically minimal rotation.
Below is the implementation of the algorithm:
C++
#include <bits/stdc++.h>
using namespace std;
// Function to find the lexicographically minimal rotation
// of a string
int findMinRotation(string s)
{
// Concatenate string to itself to avoid modular
// arithmetic
s += s;
// Initialize failure function
vector<int> failureFunc(s.size(), -1);
// Initialize least rotation of string found so far
int minRotationIdx = 0;
// Iterate over the concatenated string
for (int currentIdx = 1; currentIdx < s.size();
++currentIdx) {
char currentChar = s[currentIdx];
int failureIdx
= failureFunc[currentIdx - minRotationIdx - 1];
// Find the failure function value
while (
failureIdx != -1
&& currentChar
!= s[minRotationIdx + failureIdx + 1]) {
if (currentChar
< s[minRotationIdx + failureIdx + 1]) {
minRotationIdx
= currentIdx - failureIdx - 1;
}
failureIdx = failureFunc[failureIdx];
}
// Update the failure function and the minimum
// rotation index
if (currentChar
!= s[minRotationIdx + failureIdx + 1]) {
if (currentChar < s[minRotationIdx]) {
minRotationIdx = currentIdx;
}
failureFunc[currentIdx - minRotationIdx] = -1;
}
else {
failureFunc[currentIdx - minRotationIdx]
= failureIdx + 1;
}
}
// Return the index of the lexicographically minimal
// rotation
return minRotationIdx;
}
int main()
{
// input string
string s = "acab";
// Find the lexicographically minimal rotation
int minRotationIdx = findMinRotation(s);
// Print the lexicographically minimal rotation
cout << s.substr(minRotationIdx)
+ s.substr(0, minRotationIdx)
<< endl;
return 0;
}
Java
import java.util.Arrays;
public class Main {
// Function to find the lexicographically minimal rotation of a string
static int findMinRotation(String s) {
// Concatenate string to itself to avoid modular arithmetic
s += s;
// Initialize failure function
int[] failureFunc = new int[s.length()];
Arrays.fill(failureFunc, -1);
// Initialize least rotation of string found so far
int minRotationIdx = 0;
// Iterate over the concatenated string
for (int currentIdx = 1; currentIdx < s.length(); ++currentIdx) {
char currentChar = s.charAt(currentIdx);
int failureIdx = failureFunc[currentIdx - minRotationIdx - 1];
// Find the failure function value
while (failureIdx != -1 && currentChar != s.charAt(minRotationIdx + failureIdx + 1)) {
if (currentChar < s.charAt(minRotationIdx + failureIdx + 1)) {
minRotationIdx = currentIdx - failureIdx - 1;
}
failureIdx = failureFunc[failureIdx];
}
// Update the failure function and the minimum rotation index
if (currentChar != s.charAt(minRotationIdx + failureIdx + 1)) {
if (currentChar < s.charAt(minRotationIdx)) {
minRotationIdx = currentIdx;
}
failureFunc[currentIdx - minRotationIdx] = -1;
} else {
failureFunc[currentIdx - minRotationIdx] = failureIdx + 1;
}
}
// Return the index of the lexicographically minimal rotation
return minRotationIdx;
}
public static void main(String[] args) {
// Input string
String s = "acab";
// Find the lexicographically minimal rotation
int minRotationIdx = findMinRotation(s);
// Print the lexicographically minimal rotation
System.out.println(s.substring(minRotationIdx) + s.substring(0, minRotationIdx));
}
}
// This code is contributed by shivamgupta310570
Python
def find_min_rotation(s):
# Concatenate string to itself to avoid modular arithmetic
s += s
# Initialize failure function
failure_func = [-1] * len(s)
# Initialize least rotation of string found so far
min_rotation_idx = 0
# Iterate over the concatenated string
for current_idx in range(1, len(s)):
current_char = s[current_idx]
failure_idx = failure_func[current_idx - min_rotation_idx - 1]
# Find the failure function value
while (failure_idx != -1 and
current_char != s[min_rotation_idx + failure_idx + 1]):
if current_char < s[min_rotation_idx + failure_idx + 1]:
min_rotation_idx = current_idx - failure_idx - 1
failure_idx = failure_func[failure_idx]
# Update the failure function and the minimum rotation index
if current_char != s[min_rotation_idx + failure_idx + 1]:
if current_char < s[min_rotation_idx]:
min_rotation_idx = current_idx
failure_func[current_idx - min_rotation_idx] = -1
else:
failure_func[current_idx - min_rotation_idx] = failure_idx + 1
# Return the index of the lexicographically minimal rotation
return min_rotation_idx
def main():
# Input string
s = "acab"
# Find the lexicographically minimal rotation
min_rotation_idx = find_min_rotation(s)
# Print the lexicographically minimal rotation
print(s[min_rotation_idx:] + s[:min_rotation_idx])
if __name__ == "__main__":
main()
JavaScript
// Function to find the lexicographically minimal rotation
// of a string
function findMinRotation(s) {
// Concatenate string to itself to avoid modular
// arithmetic
s += s;
// Initialize failure function
const failureFunc = new Array(s.length).fill(-1);
// Initialize least rotation of string found so far
let minRotationIdx = 0;
// Iterate over the concatenated string
for (let currentIdx = 1; currentIdx < s.length; ++currentIdx) {
const currentChar = s.charAt(currentIdx);
let failureIdx = failureFunc[currentIdx - minRotationIdx - 1];
// Find the failure function value
while (failureIdx !== -1 && currentChar !== s.charAt(minRotationIdx + failureIdx + 1)) {
if (currentChar < s.charAt(minRotationIdx + failureIdx + 1)) {
minRotationIdx = currentIdx - failureIdx - 1;
}
failureIdx = failureFunc[failureIdx];
}
// Update the failure function and the minimum
// rotation index
if (currentChar !== s.charAt(minRotationIdx + failureIdx + 1)) {
if (currentChar < s.charAt(minRotationIdx)) {
minRotationIdx = currentIdx;
}
failureFunc[currentIdx - minRotationIdx] = -1;
} else {
failureFunc[currentIdx - minRotationIdx] = failureIdx + 1;
}
}
// Return the index of the lexicographically minimal
// rotation
return minRotationIdx;
}
// Main function
function main() {
// input string
const s = "acab";
// Find the lexicographically minimal rotation
const minRotationIdx = findMinRotation(s);
// Print the lexicographically minimal rotation
console.log(s.substring(minRotationIdx) + s.substring(0, minRotationIdx));
}
// Call the main function to execute the program
main();
Time Complexity: O(n), where n is the length of the input string s.
Auxiliary Space: O(n), where n is the length of the input string s.
Similar Reads
2D Transformation | Rotation of objects We have to rotate an object by a given angle about a given pivot point and print the new co-ordinates.Examples: Input : {(100, 100), (150, 200), (200, 200), (200, 150)} is to be rotated about (0, 0) by 90 degrees Output : (-100, 100), (-200, 150), (-200, 200), (-150, 200) Input : {(100, 100), (100,
7 min read
Minimum rotations required to delete both Strings Given two strings A and B which are permutations of each other. The task is to find the minimum number of rotations required to delete both strings completely. We can delete the first characters of both strings if they are the same. Otherwise, the string is rotated one position to left. Examples: In
11 min read
Lexicographically minimum string rotation | Set 1 Write code to find lexicographic minimum in a circular array, e.g. for the array BCABDADAB, the lexicographic minimum is ABBCABDAD.Source: Google Written Test More Examples: Input: GEEKSQUIZ Output: EEKSQUIZG Input: GFG Output: FGG Input: GEEKSFORGEEKS Output: EEKSFORGEEKSG Following is a simple sol
5 min read
Minimum rotations to unlock a circular lock You are given a lock which is made up of n-different circular rings and each ring has 0-9 digit printed serially on it. Initially all n-rings together show a n-digit integer but there is particular code only which can open the lock. You can rotate each ring any number of time in either direction. Yo
5 min read
Minimum rotations required to get the same string Given a string, we need to find the minimum number of rotations required to get the same string. Examples: Input : s = "geeks" Output : 5 Input : s = "aaaa" Output : 1 The idea is based on below post.A Program to check if strings are rotations of each other or not Step 1 : Initialize result = 0 (Her
11 min read
Check if Strings Are Rotations of Each Other Given two string s1 and s2 of same length, the task is to check whether s2 is a rotation of s1.Examples: Input: s1 = "abcd", s2 = "cdab"Output: trueExplanation: After 2 right rotations, s1 will become equal to s2.Input: s1 = "aab", s2 = "aba"Output: trueExplanation: After 1 left rotation, s1 will be
15+ min read
Rotation Count in a Rotated Sorted array Given an array arr[] having distinct numbers sorted in increasing order and the array has been right rotated (i.e, the last element will be cyclically shifted to the starting position of the array) k number of times, the task is to find the value of k.Examples: Input: arr[] = {15, 18, 2, 3, 6, 12}Ou
12 min read
How to Find Coterminal Angles? Trigonometry is a subject that involves the observation of evaluation or analysis of angles. It includes trigonometric functions and trigonometric operations for the determination of unknown angles. Trigonometry also has formulas for different operations and has standard trigonometric values or rati
4 min read
Minimum rotations required to get the same String | Set-2 Given a string, we need to find the minimum number of rotations required to get the same string. In this case, we will only consider Left rotations. Examples: Input : s = "geeks" Output : 5 Input : s = "aaaa" Output :1 Naive approach: The basic approach is to keep rotating the string from the first
10 min read
Orientation of 3 ordered points Given three points p1, p2, and p3, the task is to determine the orientation of these three points.Orientation of an ordered triplet of points in the plane can becounterclockwiseclockwisecollinearThe following diagram shows different possible orientations of (a, b, c)Â If orientation of (p1, p2, p3) i
5 min read