Circular Subsequence Shift with Deque
Last Updated :
17 Nov, 2023
Given a string S of lowercase English letters, each character is linked to one of T's unique identifiers. Specifically, character positions are associated with identifiers from 1 to T. For each identifier IDi (ranging from 1 to M), perform a clockwise/right circular shift by 1 on the portion of string S linked to identifier IDi. This operation replaces characters at positions p1, p2, ..., px in S (associated with IDi) with characters from the original S at positions
px, p1, p2, ..., px-1. Return the transformed string S after all operations.
Examples:
Input: N = 13, T = 3, S = "geeksforgeeks", ID = [1, 2,3, 1, 2, 2, 1, 1, 3, 2, 2, 1, 3]
Output: "kesgeskoeferg"
Explanation:
- First, take ID 1, and perform the operation, "keegsfkogeers".
- Then take ID 2, and perform the operation, "keegeskogfers".
- Then take ID 3, and perform the operation, "kesgeskoeferg".
Input: N = 9, T = 4, S = "algorithm", ID = [1, 4, 2, 2, 3, 4, 1, 2, 4]
Output: "tmhgrlaoi"
Explanation:
- First, take ID 1, and perform the operation, "tlgoriahm".
- Then take ID 2, and perform the operation, "tlhgriaom".
- Then take ID 3, and perform the operation, "tlhgriaom".
- Then take ID 4, and perform the operation, "tmhgrlaoi".
Approach: To solve the problem follow the below idea:
- In this approach we organizes the positions of characters with the same identifier using deque data structures, so that, it performs clockwise circular shifts on these position lists, updating their positions to simulate the circular rotation.
- Afterward, it constructs the final result string by mapping characters from the original positions to their newly shifted positions, completing the circular shift process.
- The code's efficient utilization of deque and careful manipulation of positions ensures that characters are shifted correctly within their respective colours, leading to the desired modified string output.
Steps to implement the above approach:
- Read the values of N (length of the string) and T (number of identifiers). Read the string S from the input.
- Create a vector of deques named positions of size T+1 . Each deque will store positions of characters corresponding to their identifier.
- Loop through the string S and for each character, read its associated identifier. Push the current position into the deque corresponding to that ID.
- Perform circular shifts: For each color from 1 to T, perform the following steps:
- Retrieve the deque of positions for the current ID.
- Initialize shift_amount to 1 (for clockwise shift).
- Create a new deque named shifted_pos as a copy of the original deque.
- Loop through the positions in the deque:
- Update each position in the shifted_pos deque by shifting it right by shift_amount positions (using modulo for circular effect).
- Replace the original deque with the shifted_pos deque.
- Initialize an empty string named result. For each ID from 1 to T, perform the following steps:
- Retrieve the deque of positions for the current ID.
- Loop through the positions in the deque:
- Update the character in the result string at the current position with the character from the original string S at the shifted position.
- Print the result string, which represents the final modified string after circular shifts.
Below is the implementation of the above algorithm:
C++
// C++ code for the above approach:
#include <bits/stdc++.h>
#define int long long int
using namespace std;
string transformString(int N, int T, string S,
vector<int> ID)
{
// Create a vector of deques to store positions
// of characters for each identifier
vector<deque<int> > positions(T + 1);
// Loop to populate the positions vector
// based on the identifiers
for (int i = 0; i < N; ++i) {
positions[ID[i]].push_back(i);
}
// Loop to perform clockwise circular
// shifts for each identifier
for (int identifier = 1; identifier <= T;
++identifier) {
deque<int>& pos = positions[identifier];
// Shift clockwise by 1
int shift_amount = 1;
deque<int> shifted_pos = pos;
for (int i = 0; i < pos.size(); ++i) {
// Perform circular shift by updating
// the shifted_pos deque
shifted_pos[(i + shift_amount) % pos.size()]
= pos[i];
}
// Update the original deque with
// the shifted positions
pos = shifted_pos;
}
// Initialize the result string as
// the original string
string result = S;
// Loop to construct the final modified string
// based on shifted positions
for (int identifier = 1; identifier <= T;
++identifier) {
// Get the deque of positions for
// the current identifier
const deque<int>& pos = positions[identifier];
for (int i = 0; i < pos.size(); ++i) {
// Update the result string at the
// appropriate position with the
// character from the original string
result[pos[(i + 1) % pos.size()]] = S[pos[i]];
}
}
return result;
}
// Drivers code
signed main()
{
// Length of the string and number
// of unique identifiers
int N = 13, T = 3;
// Original string
string S = "geeksforgeeks";
// Identifiers for each character
vector<int> ID
= { 1, 2, 3, 1, 2, 2, 1, 1, 3, 2, 2, 1, 3 };
// Call the function to transform the string
string transformedString = transformString(N, T, S, ID);
// Print the final modified string
cout << transformedString << endl;
return 0;
}
Java
import java.util.ArrayList;
import java.util.List;
public class CircularShiftTransformation {
public static String transformString(int N, int T, String S, int[] ID) {
// Create an array of lists to store positions of characters for each identifier
List<Integer>[] positions = new ArrayList[T + 1];
for (int i = 0; i <= T; i++) {
positions[i] = new ArrayList<>();
}
// Loop to populate the positions array based on the identifiers
for (int i = 0; i < N; i++) {
positions[ID[i]].add(i);
}
// Loop to perform clockwise circular shifts for each identifier
for (int identifier = 1; identifier <= T; identifier++) {
List<Integer> pos = positions[identifier];
// Shift clockwise by 1
int shiftAmount = 1;
List<Integer> shiftedPos = new ArrayList<>(pos);
for (int i = 0; i < pos.size(); i++) {
// Perform circular shift by updating the shiftedPos list
shiftedPos.set((i + shiftAmount) % pos.size(), pos.get(i));
}
// Update the original list with the shifted positions
positions[identifier] = shiftedPos;
}
// Initialize the result string as the original string
char[] result = S.toCharArray();
// Loop to construct the final modified string based on shifted positions
for (int identifier = 1; identifier <= T; identifier++) {
// Get the list of positions for the current identifier
List<Integer> pos = positions[identifier];
List<Integer> shiftedPos = new ArrayList<>(pos);
for (int i = 0; i < pos.size(); i++) {
// Update the result string at the appropriate position with
// the character from the original string
result[shiftedPos.get((i + 1) % pos.size())] = S.charAt(pos.get(i));
}
}
return new String(result);
}
public static void main(String[] args) {
// Length of the string and number of unique identifiers
int N = 13;
int T = 3;
// Original string
String S = "geeksforgeeks";
// Identifiers for each character
int[] ID = {1, 2, 3, 1, 2, 2, 1, 1, 3, 2, 2, 1, 3};
// Call the function to transform the string
String str = transformString(N, T, S, ID);
// Print the final modified string
System.out.println(str);
}
}
//Contributed by Aditi Tyagi
Python3
def transformString(N, T, S, ID):
# list of deques to store positions of characters for each identifier
positions = [[] for _ in range(T + 1)]
# Loop to populate the positions list based on the identifiers
for i in range(N):
positions[ID[i]].append(i)
# Loop to perform clockwise circular shifts for each identifier
for identifier in range(1, T + 1):
pos = positions[identifier]
# Shift clockwise by 1
shift_amount = 1
shifted_pos = pos[:]
for i in range(len(pos)):
# Perform circular shift by updating the shifted_pos list
shifted_pos[(i + shift_amount) % len(pos)] = pos[i]
# Update the original list with the shifted positions
positions[identifier] = shifted_pos
# Initialize the result string as the original string
result = list(S)
# Loop to construct the final modified string based on shifted positions
for identifier in range(1, T + 1):
# Get the list of positions for the current identifier
pos = positions[identifier]
for i in range(len(pos)):
# Update the result string at the appropriate position with the character from the original string
result[pos[(i + 1) % len(pos)]] = S[pos[i]]
return ''.join(result)
# Length of the string and number of unique identifiers
N = 13
T = 3
# Original string
S = "geeksforgeeks"
ID = [1, 2, 3, 1, 2, 2, 1, 1, 3, 2, 2, 1, 3]
transformedString = transformString(N, T, S, ID)
print(transformedString)
C#
using System;
using System.Collections.Generic;
class Program
{
static string TransformString(int N, int T, string S, List<int> ID)
{
// Create a list of queues to store positions of characters for each identifier
List<Queue<int>> positions = new List<Queue<int>>(T + 1);
for (int i = 0; i <= T; i++)
{
positions.Add(new Queue<int>());
}
// Populate the positions list based on the identifiers
for (int i = 0; i < N; i++)
{
positions[ID[i]].Enqueue(i);
}
// Perform clockwise circular shifts for each identifier
for (int identifier = 1; identifier <= T; identifier++)
{
Queue<int> pos = positions[identifier];
for (int i = 0; i < pos.Count; i++)
{
pos.Enqueue(pos.Dequeue());
}
}
// Initialize the result string as the original string
char[] result = S.ToCharArray();
// Construct the final modified string based on shifted positions
for (int identifier = 1; identifier <= T; identifier++)
{
Queue<int> pos = positions[identifier];
for (int i = 0; i < pos.Count; i++)
{
result[(pos.Peek() + 1) % pos.Count] = S[pos.Dequeue()];
}
}
return new string(result);
}
static void Main()
{
int N = 13;
int T = 3;
string S = "geeksforgeeks";
List<int> ID = new List<int> { 1, 2, 3, 1, 2, 2, 1, 1, 3, 2, 2, 1, 3 };
string transformedString = TransformString(N, T, S, ID);
Console.WriteLine(transformedString);
}
}
JavaScript
// JavaScript code for the above approach
function transformString(N, T, S, ID) {
// Create an array of deques to store positions of characters for each identifier
const positions = [];
for (let i = 0; i <= T; i++) {
positions.push([]);
}
// Loop to populate the positions array based on the identifiers
for (let i = 0; i < N; ++i) {
positions[ID[i]].push(i);
}
// Loop to perform clockwise circular shifts for each identifier
for (let identifier = 1; identifier <= T; ++identifier) {
const pos = positions[identifier];
// Shift clockwise by 1
const shiftAmount = 1;
const shiftedPos = [...pos];
for (let i = 0; i < pos.length; ++i) {
// Perform circular shift by updating the shiftedPos array
shiftedPos[(i + shiftAmount) % pos.length] = pos[i];
}
// Update the original array with the shifted positions
positions[identifier] = shiftedPos;
}
// Initialize the result string as the original string
const result = S.split('');
// Loop to construct the final modified string based on shifted positions
for (let identifier = 1; identifier <= T; ++identifier) {
// Get the array of positions for the current identifier
const pos = positions[identifier];
const shiftedPos = [...pos];
for (let i = 0; i < pos.length; ++i) {
// Update the result string at the appropriate position with
// the character from the original string
result[shiftedPos[(i + 1) % pos.length]] = S[pos[i]];
}
}
return result.join('');
}
// Driver code
function main() {
// Length of the string and number of unique identifiers
const N = 13;
const T = 3;
// Original string
const S = "geeksforgeeks";
// Identifiers for each character
const ID = [1, 2, 3, 1, 2, 2, 1, 1, 3, 2, 2, 1, 3];
// Call the function to transform the string
const str = transformString(N, T, S, ID);
// Print the final modified string
console.log(str);
}
main();
// This code is contributed by Abhinav Mahajan (abhinav_m22).
Time Complexity: O(T*N), the dominant factor in terms of time complexity is the circular shift operation, which takes O(T*N) time.
Auxiliary Space: O(N+T), where N is the length of the input string and T is the number of unique identifiers.
Similar Reads
Find the Longest Increasing Subsequence in Circular manner
Given an array, the task is to find LIS (Longest Increasing Subsequence) in a circular way.Examples : Input : arr[] = {5, 4, 3, 2, 1}Output : 2Although there is no LIS in a given array but in a circular form there can be{1, 5}, {2, 5}, ...... Input : arr[]= {5, 6, 7, 1, 2, 3}Output : 6{1, 2, 3, 5, 6
11 min read
What is Circular Queue | Circular Queue meaning
A circular queue is an extended version of regular queue in which the last element of the queue is connected to the first element of the queue forming a cycle. Circular Queue exampleProperties of Circular Queue: Along with the properties of a regular queue the circular queue has som other unique pro
4 min read
How to manage Full Circular Queue event?
What is a circular Queue?A circular queue is a non-primitive, linear data structure. It is an extended version of a linear queue. It is also called a Circular buffer or cyclic buffer. It offers a quick and clean way of storing First First Out (FIFO) data with a maximum size. Mainly it is used in mem
12 min read
deque::clear() and deque::erase() in C++ STL
Deque or Double-ended queues are sequence containers with the feature of expansion and contraction on both ends. They are similar to vectors, but are more efficient in the case of insertion and deletion of elements at the end, and also at the beginning. Unlike vectors, contiguous storage allocation
5 min read
Insertion in Doubly Circular Linked List
Circular Doubly Linked List has properties of both doubly linked list and circular linked list in which two consecutive elements are linked or connected by the previous and next pointer and the last node points to the first node by the next pointer and also the first node points to the last node by
15+ min read
Deletion in Doubly Circular Linked List
We have discussed the doubly circular linked list introduction and its insertion.Let us formulate the problem statement to understand the deletion process. Given a âkeyâ, delete the first occurrence of this key in the circular doubly linked list. Algorithm: Case 1: Empty List(start = NULL) If the li
15+ min read
Circular movement in a Path
Given a string S, consisting of only 3 characters 'A', 'C', or '?'. 'A' represents anti-clockwise movement, 'C' represents clockwise movement, and '?' any movement, the task is to find the maximum distance you can travel in any of the directions from the initial position. Examples: Input: S = "AC?C"
8 min read
Implementation of Deque using circular array
Deque or Double Ended Queue is a generalized version of the Queue data structure that allows insert and delete at both ends.Operations on Deque:Â Mainly the following four basic operations are performed on queue:Â insertFront(): Adds an item at the front of Deque.insertRear(): Adds an item at the rear
10 min read
Circular Queue in Python
A Circular Queue is a kind of queue that can insert elements inside it dynamically. Suppose, in a given array there is not any space left at the rear but we have space at the front in the normal queue it is not possible to insert elements at the front but in the case of a circular queue we can do th
3 min read
Generate a sequence with the given operations
Given a string S which contains only I (increase) and D (decrease). The task is to return any permutation of integers [0, 1, ..., N] where N ? Length of S such that for all i = 0, ..., N-1: If S[i] == "D", then A[i] > A[i+1]If S[i] == "I", then A[i] < A[i+1]. Note that output must contain dist
3 min read