Number of Counterclockwise shifts to make a string palindrome
Last Updated :
02 Mar, 2023
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: 2
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++
#include <bits/stdc++.h>
using namespace std;
bool isPalindrome(string str, int l, int r)
{
while (l < r) {
if (str[l] != str[r])
return false ;
l++;
r--;
}
return true ;
}
int CyclicShifts(string str)
{
int n = str.length();
int left = 0;
int right = n - 1;
str = str + str;
int cnt = 0;
while (right < 2 * n - 1) {
if (isPalindrome(str, left, right))
break ;
cnt++;
left++;
right++;
}
return cnt;
}
int main()
{
string str = "bccbbaab" ;
cout << CyclicShifts(str);
return 0;
}
|
Java
class GFG {
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 ;
}
static int CyclicShifts(String str)
{
int n = str.length();
int left = 0 ;
int right = n - 1 ;
str = str + str;
int cnt = 0 ;
while (right < 2 * n - 1 ) {
if (isPalindrome(str, left, right))
break ;
cnt++;
left++;
right++;
}
return cnt;
}
public static void main(String[] args)
{
String str = "bccbbaab" ;
System.out.println(CyclicShifts(str));
}
}
|
Python3
def isPalindrome( str , l, r):
while (l < r) :
if ( str [l] ! = str [r]):
return False
l + = 1
r - = 1
return True
def CyclicShifts( str ):
n = len ( str )
left = 0
right = n - 1
str = str + str
cnt = 0
while (right < 2 * n - 1 ) :
if (isPalindrome( str , left, right)):
break
cnt + = 1
left + = 1
right + = 1
return cnt
if __name__ = = "__main__" :
str = "bccbbaab" ;
print (CyclicShifts( str ))
|
C#
using System;
class GFG
{
static bool isPalindrome(String str, int l, int r)
{
while (l < r)
{
if (str[l] != str[r])
return false ;
l++;
r--;
}
return true ;
}
static int CyclicShifts(String str)
{
int n = str.Length;
int left = 0;
int right = n - 1;
str = str + str;
int cnt = 0;
while (right < 2 * n - 1)
{
if (isPalindrome(str, left, right))
break ;
cnt++;
left++;
right++;
}
return cnt;
}
public static void Main(String[] args)
{
String str = "bccbbaab" ;
Console.WriteLine(CyclicShifts(str));
}
}
|
Javascript
<script>
function isPalindrome(str, l, r)
{
while (l < r) {
if (str[l] != str[r])
return false ;
l++;
r--;
}
return true ;
}
function CyclicShifts(str)
{
var n = str.length;
var left = 0;
var right = n - 1;
str = str + str;
var cnt = 0;
while (right < 2 * n - 1) {
if (isPalindrome(str, left, right))
break ;
cnt++;
left++;
right++;
}
return cnt;
}
var str = "bccbbaab" ;
document.write(CyclicShifts(str));
</script>
|
complexity Analysis:
- Time Complexity: O(N2)
- Auxiliary Space: O(N)
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:
C++
#include <bits/stdc++.h>
#define mod 1000000007
using namespace std;
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 ;
}
int CyclicShifts(string str)
{
int n = str.length(), i;
if (isPalindrome(str, n))
return 0;
long long int po[2 * n + 2];
long long int preval[2 * n + 2];
long long int suffval[2 * n + 2];
long long int val1;
long long int val2;
int cnt = 0;
str = str + str;
po[0] = 1;
for (i = 1; i <= 2 * n; i++) {
po[i] = (po[i - 1] * 31) % mod;
}
for (i = 1; i <= 2 * n; i++) {
preval[i] = ((preval[i - 1] * 31) % mod + (str[i - 1] - 'a' )) % mod;
}
for (i = 2 * n; i > 0; i--) {
suffval[i] = ((suffval[i + 1] * 31) % mod + (str[i - 1] - 'a' )) % mod;
}
for (i = 1; i <= n; i++) {
val1 = (preval[i + n - 1] - ((po[n] * preval[i - 1]) % mod)) % mod;
if (val1 < 0)
val1 += mod;
val2 = (suffval[i] - ((po[n] * suffval[i + n])
% mod))
% mod;
if (val2 < 0)
val2 += mod;
if (val1 != val2)
cnt++;
else
break ;
}
return cnt;
}
int main()
{
string str = "bccbbaab" ;
cout << CyclicShifts(str);
return 0;
}
|
Java
class GFG{
static int mod = 1000000007 ;
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 ;
}
public static int CyclicShifts(String str)
{
int n = str.length(), i;
if (isPalindrome(str, n))
return 0 ;
long [] po = new long [ 2 * n + 2 ];
long [] preval = new long [ 2 * n + 2 ];
long [] suffval = new long [ 2 * n + 2 ];
long val1;
long val2;
int cnt = 0 ;
str = str + str;
po[ 0 ] = 1 ;
for (i = 1 ; i <= 2 * n; i++)
{
po[i] = (po[i - 1 ] * 31 ) % mod;
}
for (i = 1 ; i <= 2 * n; i++)
{
preval[i] = ((preval[i - 1 ] * 31 ) % mod +
(str.charAt(i - 1 ) - 'a' )) % mod;
}
for (i = 2 * n; i > 0 ; i--)
{
suffval[i] = ((suffval[i + 1 ] * 31 ) % mod +
(str.charAt(i - 1 ) - 'a' )) % mod;
}
for (i = 1 ; i <= n; i++)
{
val1 = (preval[i + n - 1 ] -
((po[n] *
preval[i - 1 ]) % mod)) % mod;
if (val1 < 0 )
val1 += mod;
val2 = (suffval[i] -
((po[n] *
suffval[i + n]) % mod)) % mod;
if (val2 < 0 )
val2 += mod;
if (val1 != val2)
cnt++;
else
break ;
}
return cnt;
}
public static void main(String[] args)
{
String str = "bccbbaab" ;
System.out.println(CyclicShifts(str));
}
}
|
Python3
mod = 1000000007
def CyclicShifts(str1):
n = len (str1)
i = 0
po = [ 0 for i in range ( 2 * n + 2 )]
preval = [ 0 for i in range ( 2 * n + 2 )]
suffval = [ 0 for i in range ( 2 * n + 2 )]
val1 = 0
val2 = 0
cnt = 0
str1 = str1 + str1
po[ 0 ] = 1
for i in range ( 1 , 2 * n + 1 ):
po[i] = (po[i - 1 ] * 31 ) % mod
for i in range ( 1 , 2 * n + 1 ):
preval[i] = ((preval[i - 1 ] * 31 ) % mod +
( ord (str1[i - 1 ]) -
ord ( 'a' ))) % mod
for i in range ( 2 * n, - 1 , - 1 ):
suffval[i] = ((suffval[i + 1 ] * 31 ) % mod +
( ord (str1[i - 1 ]) -
ord ( 'a' ))) % mod
for i in range ( 1 , n + 1 ):
val1 = (preval[i + n - 1 ] - ((po[n] *
preval[i - 1 ]) % mod)) % mod
if (val1 < 0 ):
val1 + = mod
val2 = (suffval[i] - ((po[n] *
suffval[i + n]) % mod)) % mod;
if (val2 < 0 ):
val2 + = mod
if (val1 ! = val2):
cnt + = 1
else :
break
return cnt
str1 = "bccbbaab"
print (CyclicShifts(str1))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int mod= 1000000007;
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 ;
}
static int CyclicShifts( string str)
{
int n = str.Length, i;
if (isPalindrome(str, n))
return 0;
long []po= new long [2 * n + 2];
long []preval= new long [2 * n + 2];
long []suffval= new long [2 * n + 2];
long val1;
long val2;
int cnt = 0;
str = str + str;
po[0] = 1;
for (i = 1; i <= 2 * n; i++) {
po[i] = (po[i - 1] * 31) % mod;
}
for (i = 1; i <= 2 * n; i++) {
preval[i] = ((preval[i - 1] * 31) % mod + (str[i - 1] - 'a' )) % mod;
}
for (i = 2 * n; i > 0; i--) {
suffval[i] = ((suffval[i + 1] * 31) % mod + (str[i - 1] - 'a' )) % mod;
}
for (i = 1; i <= n; i++) {
val1 = (preval[i + n - 1] - ((po[n] * preval[i - 1]) % mod)) % mod;
if (val1 < 0)
val1 += mod;
val2 = (suffval[i] - ((po[n] * suffval[i + n])
% mod))
% mod;
if (val2 < 0)
val2 += mod;
if (val1 != val2)
cnt++;
else
break ;
}
return cnt;
}
public static void Main( string []args)
{
string str = "bccbbaab" ;
Console.Write(CyclicShifts(str));
}
}
|
Javascript
let mod = 1000000007
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 CyclicShifts(str)
{
let n = str.length;
let i = 0;
if (isPalindrome(str, n))
return 0;
let po = new Array(2*n + 2).fill(0);
let preval = new Array(2*n + 2).fill(0);
let suffval = new Array(2*n + 2).fill(0);
let val1 = 0;
let val2 = 0;
let cnt = 0;
str = str + str;
po[0] = 1;
for (i = 1; i <= 2 * n; i++) {
po[i] = (po[i - 1] * 31) % mod;
}
for (i = 1; i <= 2 * n; i++) {
let temp = str[i-1].charCodeAt(0) - 97;
preval[i] = ((preval[i - 1] * 31) % mod +
(str[i - 1].charCodeAt(0) - 97)) % mod;
}
for (i = 2 * n; i > 0; i--) {
suffval[i] = ((suffval[i + 1] * 31) % mod +
(str[i - 1].charCodeAt(0) - 97)) % mod;
}
for (i = 1; i <= n; i++) {
val1 = (preval[i + n - 1] - ((po[n] * preval[i - 1]) % mod)) % mod;
if (val1 < 0)
val1 += mod;
val2 = (suffval[i] - ((po[n] * suffval[i + n]) % mod)) % mod;
if (val2 < 0)
val2 += mod;
if (val1 != val2)
cnt++;
else
break ;
}
return cnt/4;
}
let str = "bccbbaab" ;
console.log(CyclicShifts(str));
|
complexity Analysis:
- Time Complexity: O(N)
- Auxiliary Space: O(N)
Share your thoughts in the comments
Please Login to comment...