Queries on substring palindrome formation
Last Updated :
12 Sep, 2023
Given a string S, and two types of queries.
Type 1: 1 L x, Indicates update Lth index
of string S by x character.
Type 2: 2 L R, Find if characters between position L and R
of string, S can form a palindrome string.
If palindrome can be formed print "Yes",
else print "No".
1 <= L, R <= |S|
Examples:
Input : S = "geeksforgeeks"
Query 1: 1 4 g
Query 2: 2 1 4
Query 3: 2 2 3
Query 4: 1 10 t
Query 5: 2 10 11
Output :
Yes
Yes
No
Query 1: update index 3 (position 4) of string S by
character 'g'. So new string S = "geegsforgeeks".
Query 2: find if rearrangement between index 0 and 3
can form a palindrome. "geegs" is palindrome, print "Yes".
Query 3: find if rearrangement between index 1 and 2
can form a palindrome. "ee" is palindrome, print "Yes".
Query 4: update index 9 (position 10) of string S by
character 't'. So new string S = "geegsforgteks".
Query 3: find if rearrangement between index 9 and 10
can form a palindrome. "te" is not palindrome, print "No".
Substring S[L...R] form a palindrome only if frequencies of all the characters in S[L...R] are even, with one except allowed.
For query of type 1, simply update string
S[L] by character x.
For each query of type 2, calculate the
frequency of character and check if
frequencies of all characters is even (with)
one exception allowed.
Following are two different methods to find the frequency of each character in S[L...R]:
Method 1: Use a frequency array to find the frequency of each element in S[L...R].
Below is the implementation of this approach:
C++
// C++ program to Queries on substring palindrome
// formation.
#include <bits/stdc++.h>
using namespace std;
// Query type 1: update string position i with
// character x.
void qType1(int l, int x, char str[])
{
str[l - 1] = x;
}
// Print "Yes" if range [L..R] can form palindrome,
// else print "No".
void qType2(int l, int r, char str[])
{
int freq[27] = { 0 };
// Find the frequency of each character in
// S[L...R].
for (int i = l - 1; i <= r - 1; i++)
freq[str[i] - 'a']++;
// Checking if more than one character have
// frequency greater than 1.
int count = 0;
for (int j = 0; j < 26; j++)
if (freq[j] % 2)
count++;
(count <= 1) ? (cout << "Yes" << endl) : (cout << "No" << endl);
}
// Driven Program
int main()
{
char str[] = "geeksforgeeks";
int n = strlen(str);
qType1(4, 'g', str);
qType2(1, 4, str);
qType2(2, 3, str);
qType1(10, 't', str);
qType2(10, 11, str);
return 0;
}
Java
// Java program to Queries on substring
// palindrome formation.
class GFG {
// Query type 1: update string
// position i with character x.
static void qType1(int l, int x, char str[])
{
str[l - 1] = (char)x;
}
// Print "Yes" if range [L..R] can form
// palindrome, else print "No".
static void qType2(int l, int r, char str[])
{
int freq[] = new int[27];
// Find the frequency of each
// character in S[L...R].
for (int i = l - 1; i <= r - 1; i++) {
freq[str[i] - 'a']++;
}
// Checking if more than one character
// have frequency greater than 1.
int count = 0;
for (int j = 0; j < 26; j++) {
if (freq[j] % 2 != 0) {
count++;
}
}
if (count <= 1) {
System.out.println("Yes");
}
else {
System.out.println("No");
}
}
// Driven code
public static void main(String[] args)
{
char str[] = "geeksforgeeks".toCharArray();
int n = str.length;
qType1(4, 'g', str);
qType2(1, 4, str);
qType2(2, 3, str);
qType1(10, 't', str);
qType2(10, 11, str);
}
}
// This code is contributed by 29AjayKumar
Python3
# Python3 program to Queries on substring
# palindrome formation.
# Query type 1: update string position
# i with character x.
def qType1(l, x, str1):
str1[l - 1] = x
# Print"Yes" if range [L..R] can form palindrome,
# else print"No".
def qType2(l, r, str1):
freq = [0 for i in range(27)]
# Find the frequency of
# each character in S[L...R].
for i in range(l - 1, r):
freq[ord(str1[i]) - ord('a')] += 1
# Checking if more than one character
# have frequency greater than 1.
count = 0
for j in range(26):
if (freq[j] % 2):
count += 1
if count <= 1:
print("Yes")
else:
print("No")
# Driver Code
str1 = "geeksforgeeks"
str2 = [i for i in str1]
n = len(str2)
qType1(4, 'g', str2)
qType2(1, 4, str2)
qType2(2, 3, str2)
qType1(10, 't', str2)
qType2(10, 11, str2)
# This code is contributed by mohit kumar
C#
// C# program to Queries on substring
// palindrome formation.
using System;
class GFG {
// Query type 1: update string
// position i with character x.
static void qType1(int l, int x, char[] str)
{
str[l - 1] = (char)x;
}
// Print "Yes" if range [L..R] can form
// palindrome, else print "No".
static void qType2(int l, int r, char[] str)
{
int[] freq = new int[27];
// Find the frequency of each
// character in S[L...R].
for (int i = l - 1; i <= r - 1; i++) {
freq[str[i] - 'a']++;
}
// Checking if more than one character
// have frequency greater than 1.
int count = 0;
for (int j = 0; j < 26; j++) {
if (freq[j] % 2 != 0) {
count++;
}
}
if (count <= 1) {
Console.WriteLine("Yes");
}
else {
Console.WriteLine("No");
}
}
// Driver code
public static void Main(String[] args)
{
char[] str = "geeksforgeeks".ToCharArray();
int n = str.Length;
qType1(4, 'g', str);
qType2(1, 4, str);
qType2(2, 3, str);
qType1(10, 't', str);
qType2(10, 11, str);
}
}
// This code contributed by Rajput-Ji
PHP
<?php
// PHP program to Queries on substring palindrome
// formation.
// Query type 1: update string position i with
// character x.
function qType1($l, $x, &$str)
{
$str[$l - 1] = $x;
}
// Print "Yes" if range [L..R] can form palindrome,
// else print "No".
function qType2($l, $r, $str)
{
$freq=array_fill(0, 27, 0);
// Find the frequency of each character in
// S[L...R].
for ($i = $l - 1; $i <= $r - 1; $i++)
$freq[ord($str[$i]) - ord('a')]++;
// Checking if more than one character have
// frequency greater than 1.
$count = 0;
for ($j = 0; $j < 26; $j++)
if ($freq[$j] % 2)
$count++;
($count <= 1) ? (print("Yes\n")) : (print("No\n"));
}
// Driver code
$str = "geeksforgeeks";
$n = strlen($str);
qType1(4, 'g', $str);
qType2(1, 4, $str);
qType2(2, 3, $str);
qType1(10, 't', $str);
qType2(10, 11, $str);
// This code is contributed by mits
?>
JavaScript
<script>
// Javascript program to Queries on substring
// palindrome formation.
// Query type 1: update string
// position i with character x.
function qType1(l,x,str1)
{
str1[l - 1] = x;
}
// Print "Yes" if range [L..R] can form
// palindrome, else print "No".
function qType2(l,r,str1)
{
let freq = new Array(27);
for(let i=0;i<27;i++)
{
freq[i]=0;
}
// Find the frequency of each
// character in S[L...R].
for (let i = l - 1; i <= r - 1; i++) {
freq[str1[i].charCodeAt(0) - 'a'.charCodeAt(0)]++;
}
// Checking if more than one character
// have frequency greater than 1.
let count = 0;
for (let j = 0; j < 26; j++) {
if (freq[j] % 2 != 0) {
count++;
}
}
if (count <= 1) {
document.write("Yes<br>");
}
else {
document.write("No<br>");
}
}
// Driven code
let str="geeksforgeeks".split("");
let n = str.length;
qType1(4, 'g', str);
qType2(1, 4, str);
qType2(2, 3, str);
qType1(10, 't', str);
qType2(10, 11, str);
// This code is contributed by patel2127
</script>
Time Complexity: O(R-L), because qType1 function updates a single character in the string which takes O(1) time and qType2 function finds the frequency of each character in a given range of the string which takes O(R-L) time where R and L are the ending and starting indices of the range. It then checks if more than one character has a frequency greater than 1. Since the size of the frequency array is constant (26), this operation takes O(1) time. Therefore, the time complexity is O(R-L).
Space Complexity: O(1)
Method 2 : Use Binary Indexed Tree
The efficient approach can be maintain 26 Binary Index Tree for each alphabet.
Define a function getFrequency(i, u) which returns the frequency of 'u' in the ith prefix. Frequency of character 'u' in range L...R can be find by getFrequency(R, u) - getFrequency(L-1, u).
Whenever update(Query 1) comes to change S[i] from character 'u' to 'v'. BIT[u] is updated with -1 at index i and BIT[v] is updated with +1 at index i.
Below is the implementation of this approach:
C++
// C++ program to Queries on substring palindrome
// formation.
#include <bits/stdc++.h>
#define max 1000
using namespace std;
// Return the frequency of the character in the
// i-th prefix.
int getFrequency(int tree[max][27], int idx, int i)
{
int sum = 0;
while (idx > 0) {
sum += tree[idx][i];
idx -= (idx & -idx);
}
return sum;
}
// Updating the BIT
void update(int tree[max][27], int idx, int val, int i)
{
while (idx <= max) {
tree[idx][i] += val;
idx += (idx & -idx);
}
}
// Query to update the character in the string.
void qType1(int tree[max][27], int l, int x, char str[])
{
// Adding -1 at L position
update(tree, l, -1, str[l - 1] - 97 + 1);
// Updating the character
str[l - 1] = x;
// Adding +1 at R position
update(tree, l, 1, str[l - 1] - 97 + 1);
}
// Query to find if rearrangement of character in range
// L...R can form palindrome
void qType2(int tree[max][27], int l, int r, char str[])
{
int count = 0;
for (int i = 1; i <= 26; i++) {
// Checking on the first character of the string S.
if (l == 1) {
if (getFrequency(tree, r, i) % 2 == 1)
count++;
}
else {
// Checking if frequency of character is even or odd.
if ((getFrequency(tree, r, i) - getFrequency(tree, l - 1, i)) % 2 == 1)
count++;
}
}
(count <= 1) ? (cout << "Yes" << endl) : (cout << "No" << endl);
}
// Creating the Binary Index Tree of all alphabet
void buildBIT(int tree[max][27], char str[], int n)
{
memset(tree, 0, sizeof(tree));
for (int i = 0; i < n; i++)
update(tree, i + 1, 1, str[i] - 97 + 1);
}
// Driven Program
int main()
{
char str[] = "geeksforgeeks";
int n = strlen(str);
int tree[max][27];
buildBIT(tree, str, n);
qType1(tree, 4, 'g', str);
qType2(tree, 1, 4, str);
qType2(tree, 2, 3, str);
qType1(tree, 10, 't', str);
qType2(tree, 10, 11, str);
return 0;
}
Java
// Java program to Queries on substring palindrome
// formation.
import java.util.*;
class GFG {
static int max = 1000;
// Return the frequency of the character in the
// i-th prefix.
static int getFrequency(int tree[][], int idx, int i)
{
int sum = 0;
while (idx > 0) {
sum += tree[idx][i];
idx -= (idx & -idx);
}
return sum;
}
// Updating the BIT
static void update(int tree[][], int idx,
int val, int i)
{
while (idx <= max) {
tree[idx][i] += val;
idx += (idx & -idx);
}
}
// Query to update the character in the string.
static void qType1(int tree[][], int l, int x, char str[])
{
// Adding -1 at L position
update(tree, l, -1, str[l - 1] - 97 + 1);
// Updating the character
str[l - 1] = (char)x;
// Adding +1 at R position
update(tree, l, 1, str[l - 1] - 97 + 1);
}
// Query to find if rearrangement of character in range
// L...R can form palindrome
static void qType2(int tree[][], int l, int r, char str[])
{
int count = 0;
for (int i = 1; i <= 26; i++) {
// Checking on the first character of the string S.
if (l == 1) {
if (getFrequency(tree, r, i) % 2 == 1)
count++;
}
else {
// Checking if frequency of character is even or odd.
if ((getFrequency(tree, r, i) - getFrequency(tree, l - 1, i)) % 2 == 1)
count++;
}
}
if (count <= 1)
System.out.println("Yes");
else
System.out.println("No");
}
// Creating the Binary Index Tree of all alphabet
static void buildBIT(int tree[][], char str[], int n)
{
for (int i = 0; i < n; i++)
update(tree, i + 1, 1, str[i] - 97 + 1);
}
// Driver code
public static void main(String[] args)
{
char str[] = "geeksforgeeks".toCharArray();
int n = str.length;
int tree[][] = new int[max][27];
buildBIT(tree, str, n);
qType1(tree, 4, 'g', str);
qType2(tree, 1, 4, str);
qType2(tree, 2, 3, str);
qType1(tree, 10, 't', str);
qType2(tree, 10, 11, str);
}
}
/* This code contributed by PrinciRaj1992 */
Python3
# Python3 program to Queries on substring palindrome
# formation.
max = 1000;
# Return the frequency of the character in the
# i-th prefix.
def getFrequency(tree, idx, i):
sum = 0;
while (idx > 0):
sum += tree[idx][i];
idx -= (idx & -idx);
return sum;
# Updating the BIT
def update(tree, idx, val, i):
while (idx <= max):
tree[idx][i] += val;
idx += (idx & -idx);
# Query to update the character in the string.
def qType1(tree, l, x, str1):
# Adding -1 at L position
update(tree, l, -1, ord(str1[l - 1]) - 97 + 1);
# Updating the character
list1 = list(str1)
list1[l - 1] = x;
str1 = ''.join(list1);
# Adding +1 at R position
update(tree, l, 1, ord(str1[l - 1]) - 97 + 1);
# Query to find if rearrangement of character in range
# L...R can form palindrome
def qType2(tree, l, r, str1):
count = 0;
for i in range(1, 27):
# Checking on the first character of the string S.
if (l == 1):
if (getFrequency(tree, r, i) % 2 == 1):
count+=1;
else:
# Checking if frequency of character is even or odd.
if ((getFrequency(tree, r, i) -
getFrequency(tree, l - 1, i)) % 2 == 1):
count += 1;
print("Yes") if(count <= 1) else print("No");
# Creating the Binary Index Tree of all alphabet
def buildBIT(tree,str1, n):
for i in range(n):
update(tree, i + 1, 1, ord(str1[i]) - 97 + 1);
# Driver code
str1 = "geeksforgeeks";
n = len(str1);
tree = [[0 for x in range(27)] for y in range(max)];
buildBIT(tree, str1, n);
qType1(tree, 4, 'g', str1);
qType2(tree, 1, 4, str1);
qType2(tree, 2, 3, str1);
qType1(tree, 10, 't', str1);
qType2(tree, 10, 11, str1);
# This code is contributed by mits
C#
// C# program to Queries on substring palindrome
// formation.
using System;
class GFG
{
static int max = 1000;
// Return the frequency of the character in the
// i-th prefix.
static int getFrequency(int [,]tree, int idx, int i)
{
int sum = 0;
while (idx > 0)
{
sum += tree[idx,i];
idx -= (idx & -idx);
}
return sum;
}
// Updating the BIT
static void update(int [,]tree, int idx,
int val, int i)
{
while (idx <= max)
{
tree[idx,i] += val;
idx += (idx & -idx);
}
}
// Query to update the character in the string.
static void qType1(int [,]tree, int l, int x, char []str)
{
// Adding -1 at L position
update(tree, l, -1, str[l - 1] - 97 + 1);
// Updating the character
str[l - 1] = (char)x;
// Adding +1 at R position
update(tree, l, 1, str[l - 1] - 97 + 1);
}
// Query to find if rearrangement of character in range
// L...R can form palindrome
static void qType2(int [,]tree, int l, int r, char []str)
{
int count = 0;
for (int i = 1; i <= 26; i++)
{
// Checking on the first character of the string S.
if (l == 1)
{
if (getFrequency(tree, r, i) % 2 == 1)
count++;
}
else
{
// Checking if frequency of character is even or odd.
if ((getFrequency(tree, r, i) - getFrequency(tree, l - 1, i)) % 2 == 1)
count++;
}
}
if (count <= 1)
Console.WriteLine("Yes");
else
Console.WriteLine("No");
}
// Creating the Binary Index Tree of all alphabet
static void buildBIT(int [,]tree, char []str, int n)
{
for (int i = 0; i < n; i++)
update(tree, i + 1, 1, str[i] - 97 + 1);
}
// Driver code
static void Main()
{
char []str = "geeksforgeeks".ToCharArray();
int n = str.Length;
int[,] tree = new int[max,27];
buildBIT(tree, str, n);
qType1(tree, 4, 'g', str);
qType2(tree, 1, 4, str);
qType2(tree, 2, 3, str);
qType1(tree, 10, 't', str);
qType2(tree, 10, 11, str);
}
}
// This code contributed by mits
JavaScript
<script>
// Javascript program to Queries
// on substring palindrome
// formation.
let max = 1000;
// Return the frequency of the character in the
// i-th prefix.
function getFrequency(tree,idx,i)
{
let sum = 0;
while (idx > 0) {
sum += tree[idx][i];
idx -= (idx & -idx);
}
return sum;
}
// Updating the BIT
function update(tree,idx,val,i)
{
while (idx <= max) {
tree[idx][i] += val;
idx += (idx & -idx);
}
}
// Query to update the character in the string.
function qType1(tree,l,x,str)
{
// Adding -1 at L position
update(tree, l, -1,
str[l - 1].charCodeAt(0) - 97 + 1);
// Updating the character
str[l - 1] = x;
// Adding +1 at R position
update(tree, l, 1,
str[l - 1].charCodeAt(0) - 97 + 1);
}
// Query to find if rearrangement
// of character in range
// L...R can form palindrome
function qType2(tree,l,r,str)
{
let count = 0;
for (let i = 1; i <= 26; i++) {
// Checking on the first character
// of the string S.
if (l == 1) {
if (getFrequency(tree, r, i) % 2 == 1)
count++;
}
else {
// Checking if frequency of
// character is even or odd.
if ((getFrequency(tree, r, i) -
getFrequency(tree, l - 1, i)) % 2 == 1)
count++;
}
}
if (count <= 1)
document.write("Yes<br>");
else
document.write("No<br>");
}
// Creating the Binary Index Tree of all alphabet
function buildBIT(tree,str,n)
{
for (let i = 0; i < n; i++)
update(tree, i + 1, 1,
str[i].charCodeAt(0) - 97 + 1);
}
// Driver code
let str="geeksforgeeks".split("");
let n = str.length;
let tree=new Array(max);
for(let i=0;i<tree.length;i++)
{
tree[i]=new Array(27);
for(let j=0;j<tree[i].length;j++)
{
tree[i][j]=0;
}
}
buildBIT(tree, str, n);
qType1(tree, 4, 'g', str);
qType2(tree, 1, 4, str);
qType2(tree, 2, 3, str);
qType1(tree, 10, 't', str);
qType2(tree, 10, 11, str);
// This code is contributed by unknown2108
</script>
Output:
Yes
Yes
No
Time Complexity:- O(q * log n), there are q queries and every query takes O(log n) time.
Space Complexity:- O(n * 26)
Similar Reads
Palindrome Substring Queries
Given a string str of length n and a 2d array queries[][], where each query queries[i] is of type [i, j]. For each query, your task is to check if the substring str[i:j] is a palindrome.Examples : Input: str = "abaaabaaaba"queries[][] = [ [0, 10], [5, 8], [2, 5], [5, 9] ]Output: 1 0 0 1Explanation:
15+ min read
Queries to check if substring[L...R] is palindrome or not
Given a string str and Q queries. Every query consists of two numbers L and R. The task is to print if the sub-string[L...R] is palindrome or not. Examples: Input: str = "abacccde", Q[][] = {{0, 2}, {1, 2}, {2, 4}, {3, 5}} Output: Yes No No Yes Input: str = "abaaab", Q[][] = {{0, 1}, {1, 5}} Output:
12 min read
Longest Non-palindromic substring
Given a string of size n. The task is to find the length of the largest substring which is not a palindrome. Examples: Input : abba Output : 3 Here maximum length non-palindromic substring is 'abb' which is of length '3'. There could be other non-palindromic sub-strings also of length three like 'bb
7 min read
Palindrome String Coding Problems
A string is called a palindrome if the reverse of the string is the same as the original one.Example: âmadamâ, âracecarâ, â12321â.Palindrome StringProperties of a Palindrome String:A palindrome string has some properties which are mentioned below:A palindrome string has a symmetric structure which m
2 min read
Palindrome Substrings Count
Given a string s, the task is to count all palindromic substrings of length more than one.Examples:Input: s = "abaab"Output: 3Explanation: Palindromic substrings with length greater than 1, are "aba", "aa", and "baab".Input: s = "aaa"Output: 3Explanation: Palindromic substrings with length greater t
15+ min read
CSES Solution - Palindrome Queries
You are given a string that consists of n characters between aâz. The positions of the string are indexed 1,2,...n. Your task is to process m operations of the following types: Change the character at position k to xCheck if the substring from position a to position b is a palindromeInput: Each oper
13 min read
Count special palindromes in a String
Given a String s, count all special palindromic substrings of size greater than 1. A Substring is called special palindromic substring if all the characters in the substring are same or only the middle character is different for odd length. Example "aabaa" and "aaa" are special palindromic substring
11 min read
Length of Longest Palindrome Substring
Given a string S of length N, the task is to find the length of the longest palindromic substring from a given string. Examples: Input: S = "abcbab"Output: 5Explanation: string "abcba" is the longest substring that is a palindrome which is of length 5. Input: S = "abcdaa"Output: 2Explanation: string
15+ min read
Longest Palindromic Substring
Given a string s, the task is to find the longest substring which is a palindrome. If there are multiple answers, then return the first appearing substring.Examples:Input: s = "forgeeksskeegfor" Output: "geeksskeeg"Explanation: There are several possible palindromic substrings like "kssk", "ss", "ee
12 min read
Count Palindromic Substrings in a Binary String
Given a binary string S i.e. which consists only of 0's and 1's. Calculate the number of substrings of S which are palindromes. String S contains at most two 1's. Examples: Input: S = "011"Output: 4Explanation: "0", "1", "1" and "11" are the palindromic substrings. Input: S = "0" Output: 1Explanatio
7 min read