Open In App

Circular Subsequence Shift with Deque

Last Updated : 17 Nov, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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).


Output

kesgeskoeferg








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.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads