Given a string s, the task is is to check whether s can be obtained by rotating a palindrome.
Examples:
Input: s = "aaaab"
Output: 1
Explanation: The rotation "aabaa" is a palindrome and can be rotated to form "aaaab", so output is 1.Input: s = "abcd"
Output: 0
Explanation: No rotation of any palindrome can form "abcde", so output is 0.Input: s = "aab"
Output: 1
Explanation: The palindrome aba can be rotated to form "aab", so the given string is a rotated palindrome.
Table of Content
[Brute-Force Approach] Try All Possible Rotations - O(n^2) Time and O(n) Space
The idea is to check if a rotation of the string can form a palindrome. The key thought is that any rotation of a string is always a substring of the original string concatenated with itself. So, we generate all possible rotated versions by sliding a window of size n over the concatenated string and check if any of them is a palindrome using two-pointer technique. If any such substring is found, we return 1, else 0.
// C++ program to check if a given string is a
// rotation of some palindrome
#include <bits/stdc++.h>
using namespace std;
// Function to check if a string is palindrome
bool isPalindrome(string &s) {
int l = 0;
int r = s.length() - 1;
while (l < r) {
if (s[l] != s[r]) {
return false;
}
l++;
r--;
}
return true;
}
// Function to check if string is rotated palindrome
int isRotatedPalindrome(string &s) {
int n = s.length();
// Concatenate string with itself
string concat = s + s;
// Try every substring of length n
// in the concatenated string
for (int i = 0; i < n; i++) {
// Extract substring of length n
// starting from index i
string sub = concat.substr(i, n);
// Check if this substring is a palindrome
if (isPalindrome(sub)) {
return 1;
}
}
return 0;
}
int main() {
string s = "aaaab";
cout << isRotatedPalindrome(s) << endl;
return 0;
}
// Java program to check if a given string is a
// rotation of some palindrome
import java.util.*;
class GfG {
// Function to check if a string is palindrome
static boolean isPalindrome(String s) {
int l = 0;
int r = s.length() - 1;
while (l < r) {
if (s.charAt(l) != s.charAt(r)) {
return false;
}
l++;
r--;
}
return true;
}
// Function to check if string is rotated palindrome
static int isRotatedPalindrome(String s) {
int n = s.length();
// Concatenate string with itself
String concat = s + s;
// Try every substring of length n
// in the concatenated string
for (int i = 0; i < n; i++) {
// Extract substring of length n
// starting from index i
String sub = concat.substring(i, i + n);
// Check if this substring is a palindrome
if (isPalindrome(sub)) {
return 1;
}
}
return 0;
}
public static void main(String[] args) {
String s = "aaaab";
System.out.println(isRotatedPalindrome(s));
}
}
# Python program to check if a given string is a
# rotation of some palindrome
# Function to check if a string is palindrome
def isPalindrome(s):
l = 0
r = len(s) - 1
while l < r:
if s[l] != s[r]:
return False
l += 1
r -= 1
return True
# Function to check if string is rotated palindrome
def isRotatedPalindrome(s):
n = len(s)
# Concatenate string with itself
concat = s + s
# Try every substring of length n
# in the concatenated string
for i in range(n):
# Extract substring of length n
# starting from index i
sub = concat[i:i + n]
# Check if this substring is a palindrome
if isPalindrome(sub):
return 1
return 0
if __name__ == "__main__":
s = "aaaab"
print(isRotatedPalindrome(s))
// C# program to check if a given string is a
// rotation of some palindrome
using System;
class GfG {
// Function to check if a string is palindrome
static bool isPalindrome(string s) {
int l = 0;
int r = s.Length - 1;
while (l < r) {
if (s[l] != s[r]) {
return false;
}
l++;
r--;
}
return true;
}
// Function to check if string is rotated palindrome
static int isRotatedPalindrome(string s) {
int n = s.Length;
// Concatenate string with itself
string concat = s + s;
// Try every substring of length n
// in the concatenated string
for (int i = 0; i < n; i++) {
// Extract substring of length n
// starting from index i
string sub = concat.Substring(i, n);
// Check if this substring is a palindrome
if (isPalindrome(sub)) {
return 1;
}
}
return 0;
}
static void Main() {
string s = "aaaab";
Console.WriteLine(isRotatedPalindrome(s));
}
}
// JavaScript program to check if a given string is a
// rotation of some palindrome
// Function to check if a string is palindrome
function isPalindrome(s) {
let l = 0;
let r = s.length - 1;
while (l < r) {
if (s[l] !== s[r]) {
return false;
}
l++;
r--;
}
return true;
}
// Function to check if string is rotated palindrome
function isRotatedPalindrome(s) {
let n = s.length;
// Concatenate string with itself
let concat = s + s;
// Try every substring of length n
// in the concatenated string
for (let i = 0; i < n; i++) {
// Extract substring of length n
// starting from index i
let sub = concat.substring(i, i + n);
// Check if this substring is a palindrome
if (isPalindrome(sub)) {
return 1;
}
}
return 0;
}
// Driver Code
let s = "aaaab";
console.log(isRotatedPalindrome(s));
Output
1
[Expected Approach] Using Manacher's Algorithm - O(n) Time and O(n) Space
The idea is to detect any rotation of a palindrome by first doubling the string to simulate all rotations. The thought process is based on Manacher's Algorithm, which efficiently finds longest palindromic substrings in linear time. By checking if any palindromic substring of length >= original string exists in the doubled string, we can confirm a rotated palindrome. This avoids checking every rotation explicitly, leveraging palindrome expansion symmetry.
Steps to implement the above idea:
- Concatenate the original string with itself to simulate all possible rotations.
- Preprocess the string by inserting special characters like '#' to handle even-length palindromes.
- Initialize a length array P to store the radius of the palindrome centered at each index.
- Use Manacher’s algorithm to expand around each center and fill the P array efficiently.
- For every center, check if P[i] is at least equal to the original string's length.
- If such a center exists, ensure the corresponding palindrome lies within the first 2n characters.
- Return 1 if found, otherwise after the loop ends, return 0 as no valid rotation exists.
// C++ program to check if a given string is a
// rotation of some palindrome using
// Manacher's Algorithm
#include <bits/stdc++.h>
using namespace std;
// Function to check if rotated palindrome
// exists using Manacher's Algorithm
int isRotatedPalindrome(string &s) {
int n = s.length();
// Concatenate the string with itself
string concat = s + s;
// Preprocess string for Manacher's algorithm
// (insert '#' between characters)
string t = "@";
for (char c : concat) {
t += "#" + string(1, c);
}
t += "#$";
int m = t.length();
vector<int> P(m, 0);
int center = 0, right = 0;
// Manacher's algorithm core loop
for (int i = 1; i < m - 1; i++) {
int mirror = 2 * center - i;
if (i < right) {
P[i] = min(right - i, P[mirror]);
}
// Try to expand palindrome centered at i
while (t[i + (1 + P[i])] == t[i - (1 + P[i])]) {
P[i]++;
}
// Update center and right boundary
if (i + P[i] > right) {
center = i;
right = i + P[i];
}
// Check if there's a palindrome of length n
if (P[i] >= n) {
// Position of start of palindrome
// in original concat string
int start = (i - P[i]) / 2;
if (start + n <= 2 * n) {
return 1;
}
}
}
return 0;
}
int main() {
string s = "aaaab";
cout << isRotatedPalindrome(s) << endl;
return 0;
}
// Java program to check if a given string is a
// rotation of some palindrome using
// Manacher's Algorithm
class GfG {
// Function to check if rotated palindrome
// exists using Manacher's Algorithm
static int isRotatedPalindrome(String s) {
int n = s.length();
// Concatenate the string with itself
String concat = s + s;
// Preprocess string for Manacher's algorithm
// (insert '#' between characters)
StringBuilder t = new StringBuilder("@");
for (char c : concat.toCharArray()) {
t.append("#").append(c);
}
t.append("#$");
int m = t.length();
int[] P = new int[m];
int center = 0, right = 0;
// Manacher's algorithm core loop
for (int i = 1; i < m - 1; i++) {
int mirror = 2 * center - i;
if (i < right) {
P[i] = Math.min(right - i, P[mirror]);
}
// Try to expand palindrome centered at i
while (t.charAt(i + (1 + P[i])) == t.charAt(i - (1 + P[i]))) {
P[i]++;
}
// Update center and right boundary
if (i + P[i] > right) {
center = i;
right = i + P[i];
}
// Check if there's a palindrome of length n
if (P[i] >= n) {
// Position of start of palindrome
// in original concat string
int start = (i - P[i]) / 2;
if (start + n <= 2 * n) {
return 1;
}
}
}
return 0;
}
public static void main(String[] args) {
String s = "aaaab";
System.out.println(isRotatedPalindrome(s));
}
}
# Python program to check if a given string is a
# rotation of some palindrome using
# Manacher's Algorithm
def isRotatedPalindrome(s):
n = len(s)
# Concatenate the string with itself
concat = s + s
# Preprocess string for Manacher's algorithm
# (insert '#' between characters)
t = "@"
for c in concat:
t += "#" + c
t += "#$"
m = len(t)
P = [0] * m
center = 0
right = 0
# Manacher's algorithm core loop
for i in range(1, m - 1):
mirror = 2 * center - i
if i < right:
P[i] = min(right - i, P[mirror])
# Try to expand palindrome centered at i
while t[i + (1 + P[i])] == t[i - (1 + P[i])]:
P[i] += 1
# Update center and right boundary
if i + P[i] > right:
center = i
right = i + P[i]
# Check if there's a palindrome of length n
if P[i] >= n:
# Position of start of palindrome
# in original concat string
start = (i - P[i]) // 2
if start + n <= 2 * n:
return 1
return 0
if __name__ == "__main__":
s = "aaaab"
print(isRotatedPalindrome(s))
// C# program to check if a given string is a
// rotation of some palindrome using
// Manacher's Algorithm
using System;
class GfG {
// Function to check if rotated palindrome
// exists using Manacher's Algorithm
public static int isRotatedPalindrome(string s) {
int n = s.Length;
// Concatenate the string with itself
string concat = s + s;
// Preprocess string for Manacher's algorithm
// (insert '#' between characters)
string t = "@";
foreach (char c in concat) {
t += "#" + c;
}
t += "#$";
int m = t.Length;
int[] P = new int[m];
int center = 0, right = 0;
// Manacher's algorithm core loop
for (int i = 1; i < m - 1; i++) {
int mirror = 2 * center - i;
if (i < right) {
P[i] = Math.Min(right - i, P[mirror]);
}
// Try to expand palindrome centered at i
while (t[i + (1 + P[i])] == t[i - (1 + P[i])]) {
P[i]++;
}
// Update center and right boundary
if (i + P[i] > right) {
center = i;
right = i + P[i];
}
// Check if there's a palindrome of length n
if (P[i] >= n) {
// Position of start of palindrome
// in original concat string
int start = (i - P[i]) / 2;
if (start + n <= 2 * n) {
return 1;
}
}
}
return 0;
}
static void Main() {
string s = "aaaab";
Console.WriteLine(isRotatedPalindrome(s));
}
}
// JavaScript program to check if a given string is a
// rotation of some palindrome using
// Manacher's Algorithm
function isRotatedPalindrome(s) {
let n = s.length;
// Concatenate the string with itself
let concat = s + s;
// Preprocess string for Manacher's algorithm
// (insert '#' between characters)
let t = "@";
for (let c of concat) {
t += "#" + c;
}
t += "#$";
let m = t.length;
let P = new Array(m).fill(0);
let center = 0, right = 0;
// Manacher's algorithm core loop
for (let i = 1; i < m - 1; i++) {
let mirror = 2 * center - i;
if (i < right) {
P[i] = Math.min(right - i, P[mirror]);
}
// Try to expand palindrome centered at i
while (t[i + (1 + P[i])] === t[i - (1 + P[i])]) {
P[i]++;
}
// Update center and right boundary
if (i + P[i] > right) {
center = i;
right = i + P[i];
}
// Check if there's a palindrome of length n
if (P[i] >= n) {
// Position of start of palindrome
// in original concat string
let start = Math.floor((i - P[i]) / 2);
if (start + n <= 2 * n) {
return 1;
}
}
}
return 0;
}
// Driver Code
let s = "aaaab";
console.log(isRotatedPalindrome(s));
Output
1