Given a string s, check if it can be rotated to form a palindrome. Return true if it can form a palindrome otherwise, return false.
Examples:
Input: s = "aaaab"
Output: true
Explanation: "aaaab" can be rotated 2 positions to the left (or 3 positions to the right) to obtain "aabaa", which is a palindrome.Input: s = "abcd"
Output: false
Explanation: "abcd" cannot be rotated in any way to form a palindrome.Input: s = "aab"
Output: true
Explanation: "aab" can be rotated 1 positions to the left (or 2 positions to the right) to obtain "aba", which is a palindrome.
Table of Content
[Brute-Force Approach] Try All Possible Rotations - O(n^2) Time and O(n) Space
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.
#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
bool 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 true;
}
}
return false;
}
int main()
{
string s = "aaaab";
if (isRotatedPalindrome(s) == true)
{
cout << "true" << endl;
}
else
{
cout << "false" << endl;
}
return 0;
}
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 boolean 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 true;
}
}
return false;
}
public static void main(String[] args)
{
String s = "aaaab";
if (isRotatedPalindrome(s) == true) {
System.out.println("true");
}
else {
System.out.println("true");
}
}
}
# 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 True
return False
# Driver Code
if __name__ == "__main__":
s = "aaaab"
if isRotatedPalindrome(s) == True:
print("true")
else:
print("false")
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 bool 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 true;
}
}
return false;
}
static void Main()
{
string s = "aaaab";
if (isRotatedPalindrome(s) == true) {
Console.WriteLine("true");
}
else {
Console.WriteLine("false");
}
}
}
// 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 true;
}
}
return false;
}
// Driver Code
let s = "aaaab";
if (isRotatedPalindrome(s) == true) {
console.log("true");
}
else {
console.log("false");
}
Output
true
[Expected Approach] Using Manacher's Algorithm - O(n) Time and O(n) Space
- 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 true if found, otherwise after the loop ends, return false as no valid rotation exists.
#include <bits/stdc++.h>
using namespace std;
// Function to check if rotated palindrome
// exists using Manacher's Algorithm
bool 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 true;
}
}
}
return false;
}
int main()
{
string s = "aaaab";
if (isRotatedPalindrome(s) == true)
{
cout << "true" << endl;
}
else
{
cout << "false" << endl;
}
return 0;
}
class GfG {
// Function to check if rotated palindrome
// exists using Manacher's Algorithm
static boolean 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 true;
}
}
}
return false;
}
public static void main(String[] args)
{
String s = "aaaab";
if (isRotatedPalindrome(s) == true) {
System.out.println("true");
}
else {
System.out.println("false");
}
}
}
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 True
return False
# Driver Code
if __name__ == "__main__":
s = "aaaab"
if isRotatedPalindrome(s) == True:
print("true")
else:
print("false")
using System;
class GfG {
// Function to check if rotated palindrome
// exists using Manacher's Algorithm
static bool 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 true;
}
}
}
return false;
}
static void Main()
{
string s = "aaaab";
if (isRotatedPalindrome(s) == true) {
Console.WriteLine("true");
}
else {
Console.WriteLine("false");
}
}
}
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 true;
}
}
}
return false;
}
// Driver Code
let s = "aaaab";
if (isRotatedPalindrome(s) == true) {
console.log("true");
}
else {
console.log("false");
}
Output
true