Open In App

Reverse given range of String for M queries

Last Updated : 01 Feb, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given a string S of length N and an array of queries A[] of size M, the task is to find the final string after performing M operations on the string. In each operation reverse a segment of the string S from position (A[i] to N-A[i]+1).

Examples:

Input:  N = 6, S = “abcdef”, M = 3,  A =  {1, 2, 3}
Output: “fbdcea”
Explanation: After the first operation, the string will be “fedcba”. 
After the second operation it will be “fbcdea”. 
After the third operation the final string will be “fbdcea”.

Input: N = 2, S = “jc”, M = 5, A = {1, 1, 1, 1, 1}
Output: “cj”

Naive Approach:

A simple solution is to update the string after each operation by reversing it for the given range as defined by the query.

Below is the implementation of the naive approach: 

C++




// C++ program to find the string after
// M reversals on query ranges
#include <bits/stdc++.h>
using namespace std;
 
// Function for reversing string according
// to each query
void reverseForAll(string& S, int N, vector<int>& A, int M)
{
    for (int i = 0; i < M; i++) {
        int start = A[i] - 1;
        int end = N - A[i] + 1;
        reverse(S.begin() + start, S.begin() + end);
    }
}
 
// Driver Code
int main()
{
    int N = 6;
    string S = "abcdef";
    int M = 3;
    vector<int> A = { 1, 2, 3 };
 
    // Function call
    reverseForAll(S, N, A, M);
    cout << S;
    return 0;
}


Java




// Java program to find the string after M reversals on
// query ranges
import java.io.*;
 
class GFG {
 
    // Function for reversing string according
    // to each query
    public static String reverseForAll(String S, int N,
                                       int A[], int M)
    {
        String tmp = "";
 
        for (int j = 0; j < M; j++) {
            int start = A[j] - 1;
            int end = N - A[j] + 1;
            tmp = "";
            // reverse(S.begin() + start, S.begin() + end);
            // string tmp="";
            for (int i = 0; i < start; i++)
                tmp += S.charAt(i);
            for (int i = end - 1; i >= start; i--)
                tmp += S.charAt(i);
            for (int i = end; i < S.length(); i++)
                tmp += S.charAt(i);
 
            S = tmp;
        }
 
        return tmp;
    }
    // Driver Code
    public static void main(String[] args)
    {
        int N = 6;
        String S = "abcdef";
        int M = 3;
        int A[] = { 1, 2, 3 };
 
        // Function call
        String ans = reverseForAll(S, N, A, M);
        System.out.println(ans);
    }
}
// This code is contributed by Akshay
// Tripathi(akshaytripathi19410)


Python3




# Python program to find the string after
# M reversals on query ranges
 
# Function for reversing string according
# to each query
def reverseForAll( S, N, A, M):
    for i in range(0,M):
        start = A[i] - 1;
        end = N - A[i] + 1;
        S = S[:start] + "".join(reversed(S[start:end])) + S[end:];
    return S;
     
# Driver Code
N = 6;
S = "abcdef";
M = 3;
A = [ 1, 2, 3 ];
 
# Function call
S=reverseForAll(S, N, A, M);
print(S);


C#




using System;
using System.Collections.Generic;
 
class GFG {
     
    // Function for reversing string according
    // to each query
    static string reverseForAll(string S, int N, List<int> A, int M)
    {
        string tmp="";
 
        for (int j = 0; j < M; j++) {
            int start = A[j] - 1;
            int end = N - A[j] + 1;
            tmp="";
            //reverse(S.begin() + start, S.begin() + end);
            //string tmp="";
            for(int i=0; i<start; i++)
                tmp+=S[i];
            for(int i=end-1; i>=start; i--)
                tmp+=S[i];
            for(int i=end; i<S.Length; i++)
                tmp+=S[i];
             
            S=tmp;
        }
         
        return tmp;
    }
     
    // Driver Code
    public static void Main()
    {
        int N = 6;
        string S = "abcdef";
        int M = 3;
        List<int> A = new List<int>();
        A.Add(1);
        A.Add(2);
        A.Add(3);
     
        // Function call
        string ans=reverseForAll(S, N, A, M);
        Console.Write(ans);
    }
}
 
// This code is contributed by ratiagarwal.


Javascript




// Javascript program to find the string after
// M reversals on query ranges
 
// Function for reversing string according
// to each query
function reverseForAll(S, N, A, M)
{
    for (let i = 0; i < M; i++) {
        let start = A[i] - 1;
        let end = N - A[i] + 1;
        let sub = S.substring(start, end);
        sub = sub.split("").reverse().join("");
        S = S.substring(0, start) + sub + S.substring(end);
    }
    document.write(S);
}
 
// Driver Code
    let N = 6;
    let S = "abcdef";
    let M = 3;
    let A = [ 1, 2, 3 ];
 
    // Function call
    reverseForAll(S, N, A, M);


Output

fbdcea

Time Complexity: O(M*N) 
Auxiliary Space: O(1)

Efficient Approach: Please check out the Difference Array | Range update query in O(1) article before reading this approach.

Observations:

Notice that when the same section of a string is reversed twice it gains back its original state.

As in the example:

For example multiple queries of reversal on the given input

Consider (1-based Indexing) that:

  • The first reversal is to be applied to the range [1, 6].
  • The second reversal is to be applied to the range [2, 5].
  • The third reversal is to be applied to the range [3, 4].

It can be observed that:

  • reversal is applied on 1 and 6 indices one time.
  • reversal is applied on 2 and 5 indices two times.
  • reversal is applied on 3 and 4 indices three times.

In the final string, characters on indices 2 and 5 remained unchanged while indices 1, 3, 4, and 6 are reversed. So, the indices on which reversal is to be applied an even number of times do not take part in the final reversal of string while those with odd no. of reversal queries take part in reversal.

So, the idea of the efficient approach to solve this problem is:

Count for each index, how many queries include this number, if the index is included in even number of queries, it would not be reversed, otherwise if the index is included in odd number of queries it would be reversed.

Follow the steps to solve this problem:

  • Take a count array initialized to 0 with a length equal to the length of the string. This will count how many reversal queries include the corresponding index.
  • For each query, increment all the values in the range where reversal should be done.
  • This increment can be done in O(1) using the concept mentioned in the Difference Array | Range update query in O(1) article.
  • Take an empty string and traverse the count array.
  • Count array is traversed and for the indices with even value, characters at those indices from the original string are added to the answer string, otherwise, characters from the reversed string are added.

Below is the implementation of the efficient approach:

C++




// C++ program to find the string after
// M reversals on query ranges
#include <bits/stdc++.h>
using namespace std;
 
// Increments the value at first index and
// decrements at next of last index
void updateRange(vector<int>& count, int i, int j)
{
    count[i]++;
 
    // Check index out of bound
    if (j + 1 < count.size())
        count[j + 1]--;
}
 
// Prefix sum to finalise count value
// at each index
void finaliseCountArray(vector<int>& count)
{
    for (int i = 0; i < count.size(); i++)
        count[i] += count[i - 1];
}
 
// Function for reversing string according
// to each query
string reverseForAll(string S, int N, vector<int>& A, int M)
{
    vector<int> count(N, 0);
 
    // Traversal of query array
    for (int i = 0; i < M; i++) {
        int start = A[i] <= (N + 1) / 2 ? A[i] - 1 : N - A[i];
        int end = A[i] <= (N + 1) / 2 ? N - A[i] : A[i] - 1;
 
        // Increment the value of all indices
        // between both indices
        updateRange(count, start, end);
    }
 
    // Finalising count array using prefix sum
    finaliseCountArray(count);
 
    // Storing the characters at indices with
    // odd no. of reversal queries in reverse
    // manner, this stores the required indices
    // to string temp as well as temp is
    // reversed at the same time
    string temp;
    for (int i = count.size() - 1; i >= 0; i--) {
        if (count[i] % 2 != 0)
            temp.push_back(S[i]);
    }
 
    // Storing the new characters in
    // original string
    int i = 0, j = 0;
    for (i = 0; i < count.size(); i++) {
 
        // For characters with odd reversal
        // queries character is taken from
        // string temp
        if (count[i] % 2 != 0)
            S[i] = temp[j++];
 
        // If count is even then there is no
        // need to update characters as those
        // characters do not take part
        // in reversal
    }
 
    // Return final string
    return S;
}
 
// Driver Code
int main()
{
    int N = 6;
    string S = "abcdef";
    int M = 3;
    vector<int> A = { 1, 2, 3 };
 
    // Function call
    cout << reverseForAll(S, N, A, M);
    return 0;
}


Java




/*package whatever //do not write package name here */
// Java program to find the string after
// M reversals on query ranges
import java.io.*;
 
class GFG {
 
  // Increments the value at first index and
  // decrements at next of last index
  static void updateRange(int[] count, int i, int j)
  {
    count[i]++;
 
    // Check index out of bound
    if (j + 1 < count.length)
      count[j + 1]--;
  }
 
 
  // Prefix sum to finalise count value
  // at each index
  static void finaliseCountArray(int[] count)
  {
    for (int i = 1; i < count.length; i++)
      count[i] += count[i - 1];
  }
 
  // Function for reversing string according
  // to each query
  static String reverseForAll(String S, int N,int[] A, int M){
 
    int[] count = new int[N];
 
    char str[] = S.toCharArray();
 
    // Traversal of query array
    for (int i = 0; i < M; i++) {
      int start = A[i] <= (N + 1) / 2 ? A[i] - 1 : N - A[i];
      int end = A[i] <= (N + 1) / 2 ? N - A[i] : A[i] - 1;
 
      // Increment the value of all indices
      // between both indices
      updateRange(count, start, end);
    }
 
    // Finalising count array using prefix sum
    finaliseCountArray(count);
 
    // Storing the characters at indices with
    // odd no. of reversal queries in reverse
    // manner, this stores the required indices
    // to string temp as well as temp is
    // reversed at the same time
    String temp = "";
    for (int i = count.length - 1; i >= 0; i--) {
      if (count[i] % 2 != 0)
        temp += S.charAt(i);
    }
 
    // Storing the new characters in
    // original string
    int j = 0;
    for (int i = 0; i < count.length; i++) {
 
      // For characters with odd reversal
      // queries character is taken from
      // string temp
      if (count[i] % 2 != 0)
        str[i] = temp.charAt(j++);
 
      // If count is even then there is no
      // need to update characters as those
      // characters do not take part
      // in reversal
    }
 
    // Return final string
    return new String(str);
  }
 
  public static void main (String[] args) {
 
    int N = 6;
    String S = "abcdef";
    int M = 3;
    int[] A = { 1, 2, 3 };
 
    System.out.println(reverseForAll(S, N, A, M));
  }
}
 
// This code is contributed by aadityapburujwale


Python3




class GFG :
   
    # Increments the value at first index and
    # decrements at next of last index
    @staticmethod
    def updateRange( count,  i,  j) :
        count[i] += 1
         
        # Check index out of bound
        if (j + 1 < len(count)) :
            count[j + 1] -= 1
             
    # Prefix sum to finalise count value
    # at each index
    @staticmethod
    def finaliseCountArray( count) :
        i = 1
        while (i < len(count)) :
            count[i] += count[i - 1]
            i += 1
             
    # Function for reversing string according
    # to each query
    @staticmethod
    def  reverseForAll( S,  N,  A,  M) :
        count = [0] * (N)
        str = list(S)
         
        # Traversal of query array
        i = 0
        while (i < M) :
            start = A[i] - 1 if A[i] <= int((N + 1) / 2) else N - A[i]
            end = N - A[i] if A[i] <= int((N + 1) / 2) else A[i] - 1
             
            # Increment the value of all indices
            # between both indices
            GFG.updateRange(count, start, end)
            i += 1
             
        # Finalising count array using prefix sum
        GFG.finaliseCountArray(count)
         
        # Storing the characters at indices with
        # odd no. of reversal queries in reverse
        # manner, this stores the required indices
        # to string temp as well as temp is
        # reversed at the same time
        temp = ""
        i = len(count) - 1
        while (i >= 0) :
            if (count[i] % 2 != 0) :
                temp += S[i]
            i -= 1
             
        # Storing the new characters in
        # original string
        j = 0
        i = 0
        while (i < len(count)) :
           
            # For characters with odd reversal
            # queries character is taken from
            # string temp
            if (count[i] % 2 != 0) :
              j = j + 1
              str[i] = temp[j-1]
            i += 1
             
        # Return final string
        return  ''.join(str)
    @staticmethod
    def main( args) :
        N = 6
        S = "abcdef"
        M = 3
        A = [1, 2, 3]
        print(GFG.reverseForAll(S, N, A, M))
     
if __name__=="__main__":
    GFG.main([])
     
    # This code is contributed by aadityaburujwale.


C#




// Include namespace system
// C# program to find the string after
// M reversals on query ranges
using System;
 
public class GFG
{
   
    // Increments the value at first index and
    // decrements at next of last index
    public static void updateRange(int[] count, int i, int j)
    {
        count[i]++;
       
        // Check index out of bound
        if (j + 1 < count.Length)
        {
            count[j + 1]--;
        }
    }
   
    // Prefix sum to finalise count value
    // at each index
    public static void finaliseCountArray(int[] count)
    {
        for (int i = 1; i < count.Length; i++)
        {
            count[i] += count[i - 1];
        }
    }
   
    // Function for reversing string according
    // to each query
    public static String reverseForAll(String S, int N, int[] A, int M)
    {
        int[] count = new int[N];
        char[] str = S.ToCharArray();
       
        // Traversal of query array
        for (int i = 0; i < M; i++)
        {
            var start = A[i] <= (int)((N + 1) / 2) ? A[i] - 1 : N - A[i];
            var end = A[i] <= (int)((N + 1) / 2) ? N - A[i] : A[i] - 1;
           
            // Increment the value of all indices
            // between both indices
            GFG.updateRange(count, start, end);
        }
       
        // Finalising count array using prefix sum
        GFG.finaliseCountArray(count);
       
        // Storing the characters at indices with
        // odd no. of reversal queries in reverse
        // manner, this stores the required indices
        // to string temp as well as temp is
        // reversed at the same time
        var temp = "";
        for (int i = count.Length - 1; i >= 0; i--)
        {
            if (count[i] % 2 != 0)
            {
                temp += S[i];
            }
        }
       
        // Storing the new characters in
        // original string
        var j = 0;
        for (int i = 0; i < count.Length; i++)
        {
           
            // For characters with odd reversal
            // queries character is taken from
            // string temp
            if (count[i] % 2 != 0)
            {
                str[i] = temp[j++];
            }
        }
        // Return final string
        return new  String(str);
    }
    public static void Main(String[] args)
    {
        var N = 6;
        var S = "abcdef";
        var M = 3;
        int[] A = {1, 2, 3};
        Console.WriteLine(GFG.reverseForAll(S, N, A, M));
    }
}
 
// This code is contributed by aadityapburujwale


Javascript




// Function for updating the count array
function updateRange(count, i, j) {
    count[i] += 1;
    if (j + 1 < count.length) {
        count[j + 1] -= 1;
    }
}
 
// Function for finalizing the count array
function finalizeCountArray(count) {
    for (let i = 1; i < count.length; i++) {
        count[i] += count[i - 1];
    }
}
 
// Function for reversing the string according to each query
function reverseForAll(S, N, A, M) {
    let count = new Array(N).fill(0);
    let str = S.split('');
 
    // Traversal of query array
    for (let i = 0; i < M; i++) {
        let start = A[i] <= Math.ceil((N + 1) / 2) ? A[i] - 1 : N - A[i];
        let end = A[i] <= Math.ceil((N + 1) / 2) ? N - A[i] : A[i] - 1;
   
        // Increment the value of all indices between both indices
        updateRange(count, start, end);
    }
 
    // Finalizing count array using prefix sum
    finalizeCountArray(count);
 
    // Storing the characters at indices with odd no. of reversal queries in reverse manner
    // this stores the required indices to string temp as well as temp is reversed at the same time
    let temp = "";
    for (let i = count.length - 1; i >= 0; i--) {
        if (count[i] % 2 !== 0) {
            temp += S[i];
        }
    }
 
    // Storing the new characters in original string
    let j = 0;
    for (let i = 0; i < count.length; i++) {
        // For characters with odd reversal queries character is taken from string temp
        if (count[i] % 2 !== 0) {
            j++;
            str[i] = temp[j - 1];
        }
    }
 
    // Return final string
    return str.join('');
}
 
let N = 6;
let S = "abcdef";
let M = 3;
let A = [1, 2, 3];
document.write(reverseForAll(S, N, A, M));
//This code is contributed by ik_9


Output

fbdcea

Time Complexity: O(M+N) 
Auxiliary Space: O(N)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads