Open In App

Number of Counterclockwise shifts to make a string palindrome

Given a string of lowercase English alphabets, find the number of counterclockwise shifts of characters required to make the string palindrome. It is given that shifting the string will always result in the palindrome.

Examples: 

Input: str = “baabbccb” 
Output:
Shifting the string counterclockwise 2 times, 
will make the string palindrome. 
1st shift : aabbccbb 
2nd shift :abbccbba

Input: bbaabbcc 
Output: 3 
Shifting the string counterclockwise 
3 times will make the string palindrome. 
1st shift : baabbccb 
2nd shift : aabbccbb 
3rd shift : abbccbba

Naive Approach: A naive approach is to one by one shift character of the given string counter-clockwise cyclically and check if the string is palindrome or not.

Better Approach: A better approach is to append the string with itself and iterate from the first character to the last character of the given string. The substring from i to i+n (where i is in the range [0, n-1]) in the appended string will be the string obtained after every counterclockwise shift. Check for the substring if it is palindrome or not. The number of shift operations will be i.

Steps to solve this problem:

1. Declare n=str.length, left=0,right=n-1,cnt=0.

2. Concatenate the string by str=str+str.

3. While right is smaller than 2*n-1 :

    *Check if string is palindrome from left to right than break.

    *Increment cnt,left,right.

4. Return cnt. 

Below is the implementation of the above approach:




// C++ program to find counter clockwise
// shifts to make string palindrome.
#include <bits/stdc++.h>
using namespace std;
 
// Function to check if given string is
// palindrome or not.
bool isPalindrome(string str, int l, int r)
{
    while (l < r) {
        if (str[l] != str[r])
            return false;
 
        l++;
        r--;
    }
 
    return true;
}
 
// Function to find counter clockwise shifts
// to make string palindrome.
int CyclicShifts(string str)
{
 
    int n = str.length();
 
    // Pointer to starting of current
    // shifted string.
    int left = 0;
 
    // Pointer to ending of current
    // shifted string.
    int right = n - 1;
 
    // Concatenate string with itself
    str = str + str;
 
    // To store counterclockwise shifts
    int cnt = 0;
 
    // Move left and right pointers one
    // step at a time.
    while (right < 2 * n - 1) {
 
        // Check if current shifted string
        // is palindrome or not
        if (isPalindrome(str, left, right))
            break;
 
        // If string is not palindrome
        // then increase count of number
        // of shifts by 1.
        cnt++;
 
        left++;
        right++;
    }
 
    return cnt;
}
 
// Driver code.
int main()
{
    string str = "bccbbaab";
 
    cout << CyclicShifts(str);
    return 0;
}




// Java program to find counter clockwise
// shifts to make string palindrome.
class GFG {
 
    // Function to check if given string is
    // palindrome or not.
    static boolean isPalindrome(String str, int l, int r)
    {
        while (l < r) {
            if (str.charAt(l) != str.charAt(r))
                return false;
 
            l++;
            r--;
        }
        return true;
    }
 
    // Function to find counter clockwise shifts
    // to make string palindrome.
    static int CyclicShifts(String str)
    {
 
        int n = str.length();
 
        // Pointer to starting of current
        // shifted string.
        int left = 0;
 
        // Pointer to ending of current
        // shifted string.
        int right = n - 1;
 
        // Concatenate string with itself
        str = str + str;
 
        // To store counterclockwise shifts
        int cnt = 0;
 
        // Move left and right pointers one
        // step at a time.
        while (right < 2 * n - 1) {
 
            // Check if current shifted string
            // is palindrome or not
            if (isPalindrome(str, left, right))
                break;
 
            // If string is not palindrome
            // then increase count of number
            // of shifts by 1.
            cnt++;
 
            left++;
            right++;
        }
        return cnt;
    }
 
    // Driver code.
    public static void main(String[] args)
    {
        String str = "bccbbaab";
 
        System.out.println(CyclicShifts(str));
    }
}
 
// This code is contributed by Rajput-Ji




# Python3 program to find counter clockwise
# shifts to make string palindrome.
 
# Function to check if given string
# is palindrome or not.
def isPalindrome(str, l, r):
 
    while (l < r) :
        if (str[l] != str[r]):
            return False
 
        l += 1
        r -= 1
 
    return True
 
# Function to find counter clockwise
# shifts to make string palindrome.
def CyclicShifts(str):
 
    n = len(str)
 
    # Pointer to starting of current
    # shifted string.
    left = 0
 
    # Pointer to ending of current
    # shifted string.
    right = n - 1
 
    # Concatenate string with itself
    str = str + str
 
    # To store counterclockwise shifts
    cnt = 0
 
    # Move left and right pointers
    # one step at a time.
    while (right < 2 * n - 1) :
 
        # Check if current shifted string
        # is palindrome or not
        if (isPalindrome(str, left, right)):
            break
 
        # If string is not palindrome
        # then increase count of number
        # of shifts by 1.
        cnt += 1
 
        left += 1
        right += 1
 
    return cnt
 
# Driver code.
if __name__ == "__main__":
     
    str = "bccbbaab";
 
    print(CyclicShifts(str))
 
# This code is contributed by ita_c




// C# program to find counter clockwise
// shifts to make string palindrome.
using System;
 
class GFG
{
 
    // Function to check if given string is
    // palindrome or not.
    static bool isPalindrome(String str, int l, int r)
    {
        while (l < r)
        {
            if (str[l] != str[r])
                return false;
 
            l++;
            r--;
        }
        return true;
    }
 
    // Function to find counter clockwise shifts
    // to make string palindrome.
    static int CyclicShifts(String str)
    {
 
        int n = str.Length;
 
        // Pointer to starting of current
        // shifted string.
        int left = 0;
 
        // Pointer to ending of current
        // shifted string.
        int right = n - 1;
 
        // Concatenate string with itself
        str = str + str;
 
        // To store counterclockwise shifts
        int cnt = 0;
 
        // Move left and right pointers one
        // step at a time.
        while (right < 2 * n - 1)
        {
 
            // Check if current shifted string
            // is palindrome or not
            if (isPalindrome(str, left, right))
                break;
 
            // If string is not palindrome
            // then increase count of number
            // of shifts by 1.
            cnt++;
 
            left++;
            right++;
        }
        return cnt;
    }
 
    // Driver code.
    public static void Main(String[] args)
    {
        String str = "bccbbaab";
 
        Console.WriteLine(CyclicShifts(str));
    }
}
 
// This code is contributed by 29AjayKumar




<script>
 
 
// Javascript program to find counter clockwise
// shifts to make string palindrome.
 
// Function to check if given string is
// palindrome or not.
function isPalindrome(str, l, r)
{
    while (l < r) {
        if (str[l] != str[r])
            return false;
 
        l++;
        r--;
    }
 
    return true;
}
 
// Function to find counter clockwise shifts
// to make string palindrome.
function CyclicShifts(str)
{
 
    var n = str.length;
 
    // Pointer to starting of current
    // shifted string.
    var left = 0;
 
    // Pointer to ending of current
    // shifted string.
    var right = n - 1;
 
    // Concatenate string with itself
    str = str + str;
 
    // To store counterclockwise shifts
    var cnt = 0;
 
    // Move left and right pointers one
    // step at a time.
    while (right < 2 * n - 1) {
 
        // Check if current shifted string
        // is palindrome or not
        if (isPalindrome(str, left, right))
            break;
 
        // If string is not palindrome
        // then increase count of number
        // of shifts by 1.
        cnt++;
 
        left++;
        right++;
    }
 
    return cnt;
}
 
// Driver code.
var str = "bccbbaab";
document.write(CyclicShifts(str));
 
 
</script>

Output
2

complexity Analysis:

Efficient Approach: An efficient approach is to use Cumulative Hash. The string is shifted cyclically according to the method explained above and the hash value of this string is compared to the hash value of the reversed string. If both values are the same then the current shifted string is palindrome otherwise string is again shifted. The count of shifts will be i at any step. To calculate the value of both strings below hash function is used:

H(s) = ? (31i * (Si – ‘a’)) % mod, 0 ? i ? (length of string – 1) 
where, H(x) = Hash function 
s = given string 
mod = 109 + 7 

Iterate for all the substrings and check for if it is a palindrome or not using the hash function stated above and the cumulative hash technique. 

Below is the implementation of the above approach: 




// CPP program to find counter clockwise
// shifts to make string palindrome.
#include <bits/stdc++.h>
 
#define mod 1000000007
using namespace std;
 
// Function that returns true
// if str is palindrome
bool isPalindrome(string str, int n)
{
    int i = 0, j = n - 1;
    while (i < j) {
        if (str[i] != str[j])
            return false;
        i++;
        j--;
    }
    return true;
}
 
// Function to find counter clockwise shifts
// to make string palindrome.
int CyclicShifts(string str)
{
 
    int n = str.length(), i;
 
    // If the string is already a palindrome
    if (isPalindrome(str, n))
        return 0;
 
    // To store power of 31.
    // po[i] = 31^i;
    long long int po[2 * n + 2];
 
    // To store hash value of string.
    long long int preval[2 * n + 2];
 
    // To store hash value of reversed
    // string.
    long long int suffval[2 * n + 2];
 
    // To find hash value of string str[i..j]
    long long int val1;
 
    // To store hash value of reversed string
    // str[j..i]
    long long int val2;
 
    // To store number of counter clockwise
    // shifts.
    int cnt = 0;
 
    // Concatenate string with itself to shift
    // it cyclically.
    str = str + str;
 
    // Calculate powers of 31 upto 2*n which
    // will be used in hash function.
    po[0] = 1;
    for (i = 1; i <= 2 * n; i++) {
        po[i] = (po[i - 1] * 31) % mod;
    }
 
    // Hash value of string str[0..i] is stored in
    // preval[i].
    for (i = 1; i <= 2 * n; i++) {
        preval[i] = ((preval[i - 1] * 31) % mod + (str[i - 1] - 'a')) % mod;
    }
 
    // Hash value of string str[i..n-1] is stored
    // in suffval[i].
    for (i = 2 * n; i > 0; i--) {
        suffval[i] = ((suffval[i + 1] * 31) % mod + (str[i - 1] - 'a')) % mod;
    }
 
    // Characters in string str[0..i] is present
    // at position [(n-1-i)..(n-1)] in reversed
    // string. If hash value of both are same
    // then string is palindrome else not.
    for (i = 1; i <= n; i++) {
 
        // Hash value of shifted string starting at
        // index i and ending at index i+n-1.
        val1 = (preval[i + n - 1] - ((po[n] * preval[i - 1]) % mod)) % mod;
        if (val1 < 0)
            val1 += mod;
 
        // Hash value of corresponding string when
        // reversed starting at index i+n-1 and
        // ending at index i.
        val2 = (suffval[i] - ((po[n] * suffval[i + n])
                              % mod))
               % mod;
        if (val2 < 0)
            val2 += mod;
 
        // If both hash value are same then current
        // string str[i..(i+n-1)] is palindrome.
        // Else increase the shift count.
        if (val1 != val2)
            cnt++;
        else
            break;
    }
 
    return cnt;
}
 
// Driver code.
int main()
{
    string str = "bccbbaab";
 
    cout << CyclicShifts(str);
    return 0;
}




// Java program to find counter clockwise
// shifts to make string palindrome.
class GFG{
     
static int mod = 1000000007;
 
// Function that returns true
// if str is palindrome
public static boolean isPalindrome(String str, int n)
{
    int i = 0, j = n - 1;
     
    while (i < j)
    {
        if (str.charAt(i) != str.charAt(j))
            return false;
             
        i++;
        j--;
    }
    return true;
}
    
// Function to find counter clockwise shifts
// to make string palindrome.
public static int CyclicShifts(String str)
{
    int n = str.length(), i;
    
    // If the string is already a palindrome
    if (isPalindrome(str, n))
        return 0;
    
    // To store power of 31.
    // po[i] = 31^i;
    long[] po = new long[2 * n + 2];
    
    // To store hash value of string.
    long[] preval = new long[2 * n + 2];
    
    // To store hash value of reversed
    // string.
    long[] suffval = new long[2 * n + 2];
    
    // To find hash value of string str[i..j]
    long val1;
    
    // To store hash value of reversed string
    // str[j..i]
    long val2;
    
    // To store number of counter clockwise
    // shifts.
    int cnt = 0;
    
    // Concatenate string with itself to shift
    // it cyclically.
    str = str + str;
    
    // Calculate powers of 31 upto 2*n which
    // will be used in hash function.
    po[0] = 1;
     
    for(i = 1; i <= 2 * n; i++)
    {
        po[i] = (po[i - 1] * 31) % mod;
    }
    
    // Hash value of string str[0..i] is stored in
    // preval[i].
    for(i = 1; i <= 2 * n; i++)
    {
        preval[i] = ((preval[i - 1] * 31) % mod +
                 (str.charAt(i - 1) - 'a')) % mod;
    }
    
    // Hash value of string str[i..n-1] is stored
    // in suffval[i].
    for(i = 2 * n; i > 0; i--)
    {
        suffval[i] = ((suffval[i + 1] * 31) % mod +
                   (str.charAt(i - 1) - 'a')) % mod;
    }
    
    // Characters in string str[0..i] is present
    // at position [(n-1-i)..(n-1)] in reversed
    // string. If hash value of both are same
    // then string is palindrome else not.
    for(i = 1; i <= n; i++)
    {
         
        // Hash value of shifted string starting at
        // index i and ending at index i+n-1.
        val1 = (preval[i + n - 1] -
                  ((po[n] *
                preval[i - 1]) % mod)) % mod;
                 
        if (val1 < 0)
            val1 += mod;
    
        // Hash value of corresponding string when
        // reversed starting at index i+n-1 and
        // ending at index i.
        val2 = (suffval[i] -
                   ((po[n] *
                suffval[i + n]) % mod)) % mod;
                 
        if (val2 < 0)
            val2 += mod;
    
        // If both hash value are same then current
        // string str[i..(i+n-1)] is palindrome.
        // Else increase the shift count.
        if (val1 != val2)
            cnt++;
        else
            break;
    }
    return cnt;
}
 
// Driver code
public static void main(String[] args)
{
    String str = "bccbbaab";
 
    System.out.println(CyclicShifts(str));
}
}
 
// This code is contributed by divyeshrabadiya07




# Python3 program to find counter clockwise
# shifts to make string palindrome.
mod = 1000000007
 
# Function to find counter clockwise shifts
# to make string palindrome.
def CyclicShifts(str1):
 
    n = len(str1)
    i = 0
 
    # To store power of 31.
    # po[i] = 31 ^ i;
    po = [0 for i in range(2 * n + 2)]
 
    # To store hash value of string.
    preval = [0 for i in range(2 * n + 2)]
 
    # To store hash value of reversed
    # string.
    suffval = [0 for i in range(2 * n + 2)]
 
    # To find hash value of string str[i..j]
    val1 = 0
 
    # To store hash value of reversed string
    # str[j..i]
    val2 = 0
 
    # To store number of counter clockwise
    # shifts.
    cnt = 0
 
    # Concatenate string with itself to shift
    # it cyclically.
    str1 = str1 + str1
 
    # Calculate powers of 31 upto 2 * n which
    # will be used in hash function.
    po[0] = 1
    for i in range(1, 2 * n + 1):
        po[i] = (po[i - 1] * 31) % mod
 
    # Hash value of string str[0..i]
    # is stored in preval[i].
    for i in range(1, 2 * n + 1):
        preval[i] = ((preval[i - 1] * 31) % mod +
                        (ord(str1[i - 1]) -
                         ord('a'))) % mod
     
    # Hash value of string str[i..n-1] is stored
    # in suffval[i].
    for i in range(2 * n, -1, -1):
        suffval[i] = ((suffval[i + 1] * 31) % mod +
                      (ord(str1[i - 1]) -
                       ord('a'))) % mod
 
    # Characters in string str[0..i] is present
    # at position [(n-1-i)..(n-1)] in reversed
    # string. If hash value of both are same
    # then string is palindrome else not.
    for i in range(1, n + 1):
 
        # Hash value of shifted string starting at
        # index i and ending at index i + n-1.
        val1 = (preval[i + n - 1] - ((po[n] *
                preval[i - 1]) % mod)) % mod
        if (val1 < 0):
            val1 += mod
 
        # Hash value of corresponding string when
        # reversed starting at index i + n-1 and
        # ending at index i.
        val2 = (suffval[i] - ((po[n] *
                suffval[i + n])% mod)) % mod;
        if (val2 < 0):
            val2 += mod
 
        # If both hash value are same then current
        # string str[i..(i + n-1)] is palindrome.
        # Else increase the shift count.
        if (val1 != val2):
            cnt += 1
        else:
            break
     
    return cnt
 
# Driver code
str1 = "bccbbaab"
 
print(CyclicShifts(str1))
 
# This code is contributed by mohit kumar




// C# program to find counter clockwise
// shifts to make string palindrome.
using System;
using System.Collections.Generic;
 
class GFG
{
     
static int mod= 1000000007;
 
// Function that returns true
// if str is palindrome
static bool isPalindrome(string str, int n)
{
    int i = 0, j = n - 1;
    while (i < j) {
        if (str[i] != str[j])
            return false;
        i++;
        j--;
    }
    return true;
}
  
// Function to find counter clockwise shifts
// to make string palindrome.
static int CyclicShifts(string str)
{
  
    int n = str.Length, i;
  
    // If the string is already a palindrome
    if (isPalindrome(str, n))
        return 0;
  
    // To store power of 31.
    // po[i] = 31^i;
    long []po=new long[2 * n + 2];
  
    // To store hash value of string.
    long []preval=new long[2 * n + 2];
  
    // To store hash value of reversed
    // string.
    long []suffval=new long[2 * n + 2];
  
    // To find hash value of string str[i..j]
    long val1;
  
    // To store hash value of reversed string
    // str[j..i]
    long val2;
  
    // To store number of counter clockwise
    // shifts.
    int cnt = 0;
  
    // Concatenate string with itself to shift
    // it cyclically.
    str = str + str;
  
    // Calculate powers of 31 upto 2*n which
    // will be used in hash function.
    po[0] = 1;
    for (i = 1; i <= 2 * n; i++) {
        po[i] = (po[i - 1] * 31) % mod;
    }
  
    // Hash value of string str[0..i] is stored in
    // preval[i].
    for (i = 1; i <= 2 * n; i++) {
        preval[i] = ((preval[i - 1] * 31) % mod + (str[i - 1] - 'a')) % mod;
    }
  
    // Hash value of string str[i..n-1] is stored
    // in suffval[i].
    for (i = 2 * n; i > 0; i--) {
        suffval[i] = ((suffval[i + 1] * 31) % mod + (str[i - 1] - 'a')) % mod;
    }
  
    // Characters in string str[0..i] is present
    // at position [(n-1-i)..(n-1)] in reversed
    // string. If hash value of both are same
    // then string is palindrome else not.
    for (i = 1; i <= n; i++) {
  
        // Hash value of shifted string starting at
        // index i and ending at index i+n-1.
        val1 = (preval[i + n - 1] - ((po[n] * preval[i - 1]) % mod)) % mod;
        if (val1 < 0)
            val1 += mod;
  
        // Hash value of corresponding string when
        // reversed starting at index i+n-1 and
        // ending at index i.
        val2 = (suffval[i] - ((po[n] * suffval[i + n])
                              % mod))
               % mod;
        if (val2 < 0)
            val2 += mod;
  
        // If both hash value are same then current
        // string str[i..(i+n-1)] is palindrome.
        // Else increase the shift count.
        if (val1 != val2)
            cnt++;
        else
            break;
    }
  
    return cnt;
}
       
    // Driver Code
    public static void Main(string []args)
    {
         string str = "bccbbaab";
  
        Console.Write(CyclicShifts(str));
    }
}




// javascript program to find counter clockwise
// shifts to make string palindrome.
 
let mod = 1000000007
 
// Function that returns true
// if str is palindrome
function isPalindrome(str,  n)
{
    let i = 0, j = n - 1;
    while (i < j) {
        if (str[i] != str[j])
            return false;
        i++;
        j--;
    }
    return true;
}
 
// Function to find counter clockwise shifts
// to make string palindrome.
function CyclicShifts(str)
{
 
    let n = str.length;
    let i = 0;
 
    // If the string is already a palindrome
    if (isPalindrome(str, n))
        return 0;
 
    // To store power of 31.
    // po[i] = 31^i;
    let po = new Array(2*n + 2).fill(0);
 
    // To store hash value of string.
    let preval = new Array(2*n + 2).fill(0);
 
    // To store hash value of reversed
    // string.
    let suffval = new Array(2*n + 2).fill(0);
 
    // To find hash value of string str[i..j]
    let val1 = 0;
 
    // To store hash value of reversed string
    // str[j..i]
    let val2 = 0;
 
    // To store number of counter clockwise
    // shifts.
    let cnt = 0;
 
    // Concatenate string with itself to shift
    // it cyclically.
    str = str + str;
 
    // Calculate powers of 31 upto 2*n which
    // will be used in hash function.
    po[0] = 1;
    for (i = 1; i <= 2 * n; i++) {
        po[i] = (po[i - 1] * 31) % mod;
        // console.log(po[i]);
    }
 
    // Hash value of string str[0..i] is stored in
    // preval[i].
    // console.log(preval[0]);
    for (i = 1; i <= 2 * n; i++) {
        let temp = str[i-1].charCodeAt(0) - 97;
        // console.log(temp);
        preval[i] = ((preval[i - 1] * 31) % mod +
                     (str[i - 1].charCodeAt(0) - 97)) % mod;
        // console.log(preval[i]);
    }
 
    // Hash value of string str[i..n-1] is stored
    // in suffval[i].
    for (i = 2 * n; i > 0; i--) {
        suffval[i] = ((suffval[i + 1] * 31) % mod +
                      (str[i - 1].charCodeAt(0) - 97)) % mod;
    }
 
    // Characters in string str[0..i] is present
    // at position [(n-1-i)..(n-1)] in reversed
    // string. If hash value of both are same
    // then string is palindrome else not.
    for (i = 1; i <= n; i++) {
 
        // Hash value of shifted string starting at
        // index i and ending at index i+n-1.
        val1 = (preval[i + n - 1] - ((po[n] * preval[i - 1]) % mod)) % mod;
        if (val1 < 0)
            val1 += mod;
 
        // Hash value of corresponding string when
        // reversed starting at index i+n-1 and
        // ending at index i.
        val2 = (suffval[i] - ((po[n] * suffval[i + n]) % mod)) % mod;
        if (val2 < 0)
            val2 += mod;
 
        // If both hash value are same then current
        // string str[i..(i+n-1)] is palindrome.
        // Else increase the shift count.
        if (val1 != val2)
            cnt++;
        else
            break;
    }
 
    return cnt/4;
}
 
// Driver code.
let str = "bccbbaab";
 
console.log(CyclicShifts(str));
 
// The code is contributed by Arushi jindal.

Output
2

complexity Analysis:


Article Tags :