Minimum move to end operations to make all strings equal
Last Updated :
16 May, 2024
Given n strings that are permutations of each other. We need to make all strings same with an operation that takes front character of any string and moves it to the end.
Examples:
Input: n = 2, arr[] = {"molzv", "lzvmo"}
Output: 2
Explanation: In first string, we remove first element("m") from first string and append it end. Then we move second character of first string and move it to end. So after 2 operations, both strings become same.
Input: n = 3, arr[] = {"kc", "kc", "kc"}
Output: 0
Explanation: already all strings are equal.
Approach:
The move to end operation is basically left rotation. We use the approach discussed in check if strings are rotations of each other or not to count a number of move to front operations required to make two strings the same. We one by one consider every string as the target string. We count rotations required to make all other strings the same as the current target and finally return a minimum of all counts.
Below is the implementation of the above approach.
C++
// CPP program to make all strings same using
// move to end operations.
#include <bits/stdc++.h>
using namespace std;
// Returns minimum number of moves to end
// operations to make all strings same.
int minimunMoves(string arr[], int n)
{
int ans = INT_MAX;
for (int i = 0; i < n; i++)
{
int curr_count = 0;
// Consider s[i] as target string and
// count rotations required to make
// all other strings same as str[i].
for (int j = 0; j < n; j++) {
string tmp = arr[j] + arr[j];
// find function returns the index where we
// found arr[i] which is actually count of
// move-to-front operations.
int index = tmp.find(arr[i]);
// If any two strings are not rotations of
// each other, we can't make them same.
if (index == string::npos)
return -1;
curr_count += index;
}
ans = min(curr_count, ans);
}
return ans;
}
// driver code for above function.
int main()
{
string arr[] = {"xzzwo", "zwoxz", "zzwox", "xzzwo"};
int n = sizeof(arr)/sizeof(arr[0]);
cout << minimunMoves(arr, n);
return 0;
}
Java
// Java program to make all
// strings same using move
// to end operations.
import java.util.*;
class GFG
{
// Returns minimum number of
// moves to end operations
// to make all strings same.
static int minimunMoves(String arr[], int n)
{
int ans = Integer.MAX_VALUE;
for (int i = 0; i < n; i++)
{
int curr_count = 0;
// Consider s[i] as target
// string and count rotations
// required to make all other
// strings same as str[i].
String tmp = "";
for (int j = 0; j < n; j++)
{
tmp = arr[j] + arr[j];
// find function returns the
// index where we found arr[i]
// which is actually count of
// move-to-front operations.
int index = tmp.indexOf(arr[i]);
// If any two strings are not
// rotations of each other,
// we can't make them same.
if (index != -1)
curr_count += index;
else
curr_count = -1;
}
ans = Math.min(curr_count, ans);
}
return ans;
}
// Driver code
public static void main(String args[])
{
String arr[] = {"xzzwo", "zwoxz",
"zzwox", "xzzwo"};
int n = arr.length;
System.out.println(minimunMoves(arr, n));
}
}
// This code is contributed
// by Kirti_Mangal
Python
# Python 3 program to make all strings
# same using move to end operations.
import sys
# Returns minimum number of moves to end
# operations to make all strings same.
def minimunMoves(arr, n):
ans = sys.maxsize
for i in range(n):
curr_count = 0
# Consider s[i] as target string and
# count rotations required to make
# all other strings same as str[i].
for j in range(n):
tmp = arr[j] + arr[j]
# find function returns the index where
# we found arr[i] which is actually
# count of move-to-front operations.
index = tmp.find(arr[i])
# If any two strings are not rotations of
# each other, we can't make them same.
if (index == len(arr[i])):
return -1
curr_count += index
ans = min(curr_count, ans)
return ans
# Driver Code
if __name__ == "__main__":
arr = ["xzzwo", "zwoxz", "zzwox", "xzzwo"]
n = len(arr)
print( minimunMoves(arr, n))
# This code is contributed by ita_c
C#
using System;
// C# program to make all
// strings same using move
// to end operations.
public class GFG
{
// Returns minimum number of
// moves to end operations
// to make all strings same.
public static int minimunMoves(string[] arr, int n)
{
int ans = int.MaxValue;
for (int i = 0; i < n; i++)
{
int curr_count = 0;
// Consider s[i] as target
// string and count rotations
// required to make all other
// strings same as str[i].
string tmp = "";
for (int j = 0; j < n; j++)
{
tmp = arr[j] + arr[j];
// find function returns the
// index where we found arr[i]
// which is actually count of
// move-to-front operations.
int index = tmp.IndexOf(arr[i], StringComparison.Ordinal);
// If any two strings are not
// rotations of each other,
// we can't make them same.
if (index == arr[i].Length)
{
return -1;
}
curr_count += index;
}
ans = Math.Min(curr_count, ans);
}
return ans;
}
// Driver code
public static void Main(string[] args)
{
string[] arr = new string[] {"xzzwo", "zwoxz", "zzwox", "xzzwo"};
int n = arr.Length;
Console.WriteLine(minimunMoves(arr, n));
}
}
// This code is contributed by Shrikant13
JavaScript
<script>
// Javascript program to make all
// strings same using move
// to end operations.
// Returns minimum number of
// moves to end operations
// to make all strings same.
function minimunMoves(arr,n)
{
let ans = Number.MAX_VALUE;
for (let i = 0; i < n; i++)
{
let curr_count = 0;
// Consider s[i] as target
// string and count rotations
// required to make all other
// strings same as str[i].
let tmp = "";
for (let j = 0; j < n; j++)
{
tmp = arr[j] + arr[j];
// find function returns the
// index where we found arr[i]
// which is actually count of
// move-to-front operations.
let index = tmp.indexOf(arr[i]);
// If any two strings are not
// rotations of each other,
// we can't make them same.
if (index == arr[i].length)
return -1;
curr_count += index;
}
ans = Math.min(curr_count, ans);
}
return ans;
}
// Driver code
let arr=["xzzwo", "zwoxz",
"zzwox", "xzzwo"];
let n = arr.length;
document.write(minimunMoves(arr, n));
// This code is contributed by avanitrachhadiya2155
</script>
Time Complexity : O(n3), Where n is the size of given string (n2 for the two nested for loops and n is for the function used as find())
Auxiliary Space: O(n)
To efficiently determine the minimum number of moves required to make all strings in an array identical by rotating characters, we can use the KMP algorithm. This approach leverages the ability of the KMP algorithm to find substring matches efficiently, which helps in quickly determining how many rotations are needed to transform one string into another.
This method revolves around using KMP for pattern searching, which allows us to detect the smallest shift needed for one string to become another. Instead of performing a find operation on concatenated strings (which is computationally expensive), we preprocess the target string to create a partial match table (or pi table). Using this table, we can efficiently determine how many rotations are needed to align one string to another. This reduces the number of operations significantly compared to the naive method.
- Preprocess all Strings: Compute the KMP tables for all strings in advance. This allows us to quickly compare any string against another using the KMP search method.
- Compute Rotations for Each Target: For each string considered as the potential final form, compute how many rotations are required for all other strings to match this target.
- Select Minimum Rotations: Track and return the minimum number of rotations across all potential target strings.
Below is the implementation of the above approach:
C++
#include <algorithm>
#include <bits/stdc++.h>
#include <iostream>
#include <string>
#include <vector>
// Function to compute the KMP table for a given pattern
std::vector<int> computeKMPTable(const std::string& s)
{
std::vector<int> pi(s.size(), 0);
int j = 0;
for (int i = 1; i < s.size(); ++i) {
while (j > 0 && s[i] != s[j]) {
j = pi[j - 1];
}
if (s[i] == s[j]) {
j++;
pi[i] = j;
}
}
return pi;
}
// Function to perform KMP search for a pattern in a text
int KMPsearch(const std::string& text,
const std::string& pattern,
const std::vector<int>& pi)
{
int j = 0;
for (int i = 0; i < text.size(); ++i) {
while (j > 0 && text[i] != pattern[j]) {
j = pi[j - 1];
}
if (text[i] == pattern[j]) {
if (j == pattern.size() - 1) {
return i - j; // Match found at index i - j
j = pi[j];
}
else {
j++;
}
}
}
return -1; // No match found
}
// Function to find the minimum moves to make all strings
// equal by rotating
int minimumMoves(const std::vector<std::string>& arr)
{
int n = arr.size();
int ans = INT_MAX;
std::vector<std::vector<int> > kmpTables(n);
// Compute KMP tables for all strings
for (int i = 0; i < n; ++i) {
kmpTables[i] = computeKMPTable(arr[i]);
}
// Iterate over each string to find the minimum rotation
// count
for (int i = 0; i < n; ++i) {
int currCount = 0;
const std::string& target = arr[i];
const std::vector<int>& pi = kmpTables[i];
for (int j = 0; j < n; ++j) {
if (i == j) {
continue; // Skip self
}
std::string doubleStr = arr[j] + arr[j];
int rotationIndex
= KMPsearch(doubleStr, target, pi);
if (rotationIndex == -1) {
return -1; // Not possible to match
}
currCount += rotationIndex;
}
ans = std::min(ans, currCount);
}
return ans;
}
int main()
{
std::vector<std::string> arr
= { "xzzwo", "zwoxz", "zzwox", "xzzwo" };
std::cout << minimumMoves(arr)
<< std::endl; // Output should be optimized
// rotation count
return 0;
}
Java
import java.util.ArrayList;
import java.util.List;
public class Main {
// Function to compute the KMP table for a given pattern
public static List<Integer> computeKMPTable(String s)
{
List<Integer> pi = new ArrayList<>(s.length());
for (int i = 0; i < s.length(); i++) {
pi.add(0);
}
int j = 0;
for (int i = 1; i < s.length(); ++i) {
while (j > 0 && s.charAt(i) != s.charAt(j)) {
j = pi.get(j - 1);
}
if (s.charAt(i) == s.charAt(j)) {
j++;
pi.set(i, j);
}
}
return pi;
}
// Function to perform KMP search for a pattern in a
// text
public static int KMPsearch(String text, String pattern,
List<Integer> pi)
{
int j = 0;
for (int i = 0; i < text.length(); ++i) {
while (j > 0
&& text.charAt(i) != pattern.charAt(j)) {
j = pi.get(j - 1);
}
if (text.charAt(i) == pattern.charAt(j)) {
if (j == pattern.length() - 1) {
return i
- j; // Match found at index i - j
}
else {
j++;
}
}
}
return -1; // No match found
}
// Function to find the minimum moves to make all
// strings equal by rotating
public static int minimumMoves(List<String> arr)
{
int n = arr.size();
int ans = Integer.MAX_VALUE;
List<List<Integer> > kmpTables = new ArrayList<>(n);
// Compute KMP tables for all strings
for (int i = 0; i < n; ++i) {
kmpTables.add(computeKMPTable(arr.get(i)));
}
// Iterate over each string to find the minimum
// rotation count
for (int i = 0; i < n; ++i) {
int currCount = 0;
String target = arr.get(i);
List<Integer> pi = kmpTables.get(i);
for (int j = 0; j < n; ++j) {
if (i == j) {
continue; // Skip self
}
String doubleStr = arr.get(j) + arr.get(j);
int rotationIndex
= KMPsearch(doubleStr, target, pi);
if (rotationIndex == -1) {
return -1; // Not possible to match
}
currCount += rotationIndex;
}
ans = Math.min(ans, currCount);
}
return ans;
}
public static void main(String[] args)
{
List<String> arr
= List.of("xzzwo", "zwoxz", "zzwox", "xzzwo");
System.out.println(minimumMoves(arr));
}
}
// This code is contributed by shivamgupta0987654321
Python
def computeKMPTable(s):
pi = [0] * len(s)
j = 0
for i in range(1, len(s)):
while j > 0 and s[i] != s[j]:
j = pi[j - 1]
if s[i] == s[j]:
j += 1
pi[i] = j
return pi
def KMPsearch(text, pattern, pi):
j = 0
for i in range(len(text)):
while j > 0 and text[i] != pattern[j]:
j = pi[j - 1]
if text[i] == pattern[j]:
if j == len(pattern) - 1:
return i - j # Match found at index i - j
j = pi[j]
else:
j += 1
return -1 # No match found
def minimumMoves(arr):
n = len(arr)
ans = float('inf')
kmp_tables = [computeKMPTable(s) for s in arr]
for i in range(n):
curr_count = 0
target = arr[i]
pi = kmp_tables[i]
for j in range(n):
if i == j:
continue
double_str = arr[j] + arr[j]
rotation_index = KMPsearch(double_str, target, pi)
if rotation_index == -1:
return -1 # Not possible to match
curr_count += rotation_index
ans = min(ans, curr_count)
return ans
# Example usage:
arr = ["xzzwo", "zwoxz", "zzwox", "xzzwo"]
print(minimumMoves(arr)) # Output should be optimized rotation count
JavaScript
function computeKMPTable(s) {
const pi = new Array(s.length).fill(0);
let j = 0;
for (let i = 1; i < s.length; i++) {
while (j > 0 && s[i] !== s[j]) {
j = pi[j - 1];
}
if (s[i] === s[j]) {
j++;
pi[i] = j;
}
}
return pi;
}
function KMPsearch(text, pattern, pi) {
let j = 0;
for (let i = 0; i < text.length; i++) {
while (j > 0 && text[i] !== pattern[j]) {
j = pi[j - 1];
}
if (text[i] === pattern[j]) {
if (j === pattern.length - 1) {
return i - j; // Match found at index i - j
j = pi[j];
} else {
j++;
}
}
}
return -1; // No match found
}
function minimumMoves(arr) {
const n = arr.length;
let ans = Infinity;
const kmpTables = arr.map(s => computeKMPTable(s));
for (let i = 0; i < n; i++) {
let currCount = 0;
const target = arr[i];
const pi = kmpTables[i];
for (let j = 0; j < n; j++) {
if (i === j) {
continue;
}
const doubleStr = arr[j] + arr[j];
const rotationIndex = KMPsearch(doubleStr, target, pi);
if (rotationIndex === -1) {
return -1; // Not possible to match
}
currCount += rotationIndex;
}
ans = Math.min(ans, currCount);
}
return ans;
}
// Example usage:
const arr = ["xzzwo", "zwoxz", "zzwox", "xzzwo"];
console.log(minimumMoves(arr)); // Output should be optimized rotation count
Time Complexity: O(n^2×m), where m is the length of the longest string.
Auxiliary Space: O(m)
Similar Reads
Basics & Prerequisites
Data Structures
Array Data StructureIn this article, we introduce array, implementation in different popular languages, its basic operations and commonly seen problems / interview questions. An array stores items (in case of C/C++ and Java Primitive Arrays) or their references (in case of Python, JS, Java Non-Primitive) at contiguous
3 min read
String in Data StructureA string is a sequence of characters. The following facts make string an interesting data structure.Small set of elements. Unlike normal array, strings typically have smaller set of items. For example, lowercase English alphabet has only 26 characters. ASCII has only 256 characters.Strings are immut
2 min read
Hashing in Data StructureHashing is a technique used in data structures that efficiently stores and retrieves data in a way that allows for quick access. Hashing involves mapping data to a specific index in a hash table (an array of items) using a hash function. It enables fast retrieval of information based on its key. The
2 min read
Linked List Data StructureA linked list is a fundamental data structure in computer science. It mainly allows efficient insertion and deletion operations compared to arrays. Like arrays, it is also used to implement other data structures like stack, queue and deque. Hereâs the comparison of Linked List vs Arrays Linked List:
2 min read
Stack Data StructureA Stack is a linear data structure that follows a particular order in which the operations are performed. The order may be LIFO(Last In First Out) or FILO(First In Last Out). LIFO implies that the element that is inserted last, comes out first and FILO implies that the element that is inserted first
2 min read
Queue Data StructureA Queue Data Structure is a fundamental concept in computer science used for storing and managing data in a specific order. It follows the principle of "First in, First out" (FIFO), where the first element added to the queue is the first one to be removed. It is used as a buffer in computer systems
2 min read
Tree Data StructureTree Data Structure is a non-linear data structure in which a collection of elements known as nodes are connected to each other via edges such that there exists exactly one path between any two nodes. Types of TreeBinary Tree : Every node has at most two childrenTernary Tree : Every node has at most
4 min read
Graph Data StructureGraph Data Structure is a collection of nodes connected by edges. It's used to represent relationships between different entities. If you are looking for topic-wise list of problems on different topics like DFS, BFS, Topological Sort, Shortest Path, etc., please refer to Graph Algorithms. Basics of
3 min read
Trie Data StructureThe Trie data structure is a tree-like structure used for storing a dynamic set of strings. It allows for efficient retrieval and storage of keys, making it highly effective in handling large datasets. Trie supports operations such as insertion, search, deletion of keys, and prefix searches. In this
15+ min read
Algorithms
Searching AlgorithmsSearching algorithms are essential tools in computer science used to locate specific items within a collection of data. In this tutorial, we are mainly going to focus upon searching in an array. When we search an item in an array, there are two most common algorithms used based on the type of input
2 min read
Sorting AlgorithmsA Sorting Algorithm is used to rearrange a given array or list of elements in an order. For example, a given array [10, 20, 5, 2] becomes [2, 5, 10, 20] after sorting in increasing order and becomes [20, 10, 5, 2] after sorting in decreasing order. There exist different sorting algorithms for differ
3 min read
Introduction to RecursionThe process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called a recursive function. A recursive algorithm takes one step toward solution and then recursively call itself to further move. The algorithm stops once we reach the solution
14 min read
Greedy AlgorithmsGreedy algorithms are a class of algorithms that make locally optimal choices at each step with the hope of finding a global optimum solution. At every step of the algorithm, we make a choice that looks the best at the moment. To make the choice, we sometimes sort the array so that we can always get
3 min read
Graph AlgorithmsGraph is a non-linear data structure like tree data structure. The limitation of tree is, it can only represent hierarchical data. For situations where nodes or vertices are randomly connected with each other other, we use Graph. Example situations where we use graph data structure are, a social net
3 min read
Dynamic Programming or DPDynamic Programming is an algorithmic technique with the following properties.It is mainly an optimization over plain recursion. Wherever we see a recursive solution that has repeated calls for the same inputs, we can optimize it using Dynamic Programming. The idea is to simply store the results of
3 min read
Bitwise AlgorithmsBitwise algorithms in Data Structures and Algorithms (DSA) involve manipulating individual bits of binary representations of numbers to perform operations efficiently. These algorithms utilize bitwise operators like AND, OR, XOR, NOT, Left Shift, and Right Shift.BasicsIntroduction to Bitwise Algorit
4 min read
Advanced
Segment TreeSegment Tree is a data structure that allows efficient querying and updating of intervals or segments of an array. It is particularly useful for problems involving range queries, such as finding the sum, minimum, maximum, or any other operation over a specific range of elements in an array. The tree
3 min read
Pattern SearchingPattern searching algorithms are essential tools in computer science and data processing. These algorithms are designed to efficiently find a particular pattern within a larger set of data. Patten SearchingImportant Pattern Searching Algorithms:Naive String Matching : A Simple Algorithm that works i
2 min read
GeometryGeometry is a branch of mathematics that studies the properties, measurements, and relationships of points, lines, angles, surfaces, and solids. From basic lines and angles to complex structures, it helps us understand the world around us.Geometry for Students and BeginnersThis section covers key br
2 min read
Interview Preparation
Practice Problem