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++
#include <bits/stdc++.h>
using namespace std;
void qType1( int l, int x, char str[])
{
str[l - 1] = x;
}
void qType2( int l, int r, char str[])
{
int freq[27] = { 0 };
for ( int i = l - 1; i <= r - 1; i++)
freq[str[i] - 'a' ]++;
int count = 0;
for ( int j = 0; j < 26; j++)
if (freq[j] % 2)
count++;
(count <= 1) ? (cout << "Yes" << endl) : (cout << "No" << endl);
}
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
class GFG {
static void qType1( int l, int x, char str[])
{
str[l - 1 ] = ( char )x;
}
static void qType2( int l, int r, char str[])
{
int freq[] = new int [ 27 ];
for ( int i = l - 1 ; i <= r - 1 ; i++) {
freq[str[i] - 'a' ]++;
}
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" );
}
}
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);
}
}
|
Python3
def qType1(l, x, str1):
str1[l - 1 ] = x
def qType2(l, r, str1):
freq = [ 0 for i in range ( 27 )]
for i in range (l - 1 , r):
freq[ ord (str1[i]) - ord ( 'a' )] + = 1
count = 0
for j in range ( 26 ):
if (freq[j] % 2 ):
count + = 1
if count < = 1 :
print ( "Yes" )
else :
print ( "No" )
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)
|
C#
using System;
class GFG {
static void qType1( int l, int x, char [] str)
{
str[l - 1] = ( char )x;
}
static void qType2( int l, int r, char [] str)
{
int [] freq = new int [27];
for ( int i = l - 1; i <= r - 1; i++) {
freq[str[i] - 'a' ]++;
}
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" );
}
}
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);
}
}
|
PHP
<?php
function qType1( $l , $x , & $str )
{
$str [ $l - 1] = $x ;
}
function qType2( $l , $r , $str )
{
$freq = array_fill (0, 27, 0);
for ( $i = $l - 1; $i <= $r - 1; $i ++)
$freq [ord( $str [ $i ]) - ord( 'a' )]++;
$count = 0;
for ( $j = 0; $j < 26; $j ++)
if ( $freq [ $j ] % 2)
$count ++;
( $count <= 1) ? ( print ( "Yes\n" )) : ( print ( "No\n" ));
}
$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 );
?>
|
Javascript
<script>
function qType1(l,x,str1)
{
str1[l - 1] = x;
}
function qType2(l,r,str1)
{
let freq = new Array(27);
for (let i=0;i<27;i++)
{
freq[i]=0;
}
for (let i = l - 1; i <= r - 1; i++) {
freq[str1[i].charCodeAt(0) - 'a' .charCodeAt(0)]++;
}
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>" );
}
}
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);
</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++
#include <bits/stdc++.h>
#define max 1000
using namespace std;
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;
}
void update( int tree[max][27], int idx, int val, int i)
{
while (idx <= max) {
tree[idx][i] += val;
idx += (idx & -idx);
}
}
void qType1( int tree[max][27], int l, int x, char str[])
{
update(tree, l, -1, str[l - 1] - 97 + 1);
str[l - 1] = x;
update(tree, l, 1, str[l - 1] - 97 + 1);
}
void qType2( int tree[max][27], int l, int r, char str[])
{
int count = 0;
for ( int i = 1; i <= 26; i++) {
if (l == 1) {
if (getFrequency(tree, r, i) % 2 == 1)
count++;
}
else {
if ((getFrequency(tree, r, i) - getFrequency(tree, l - 1, i)) % 2 == 1)
count++;
}
}
(count <= 1) ? (cout << "Yes" << endl) : (cout << "No" << endl);
}
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);
}
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
import java.util.*;
class GFG {
static int max = 1000 ;
static int getFrequency( int tree[][], int idx, int i)
{
int sum = 0 ;
while (idx > 0 ) {
sum += tree[idx][i];
idx -= (idx & -idx);
}
return sum;
}
static void update( int tree[][], int idx,
int val, int i)
{
while (idx <= max) {
tree[idx][i] += val;
idx += (idx & -idx);
}
}
static void qType1( int tree[][], int l, int x, char str[])
{
update(tree, l, - 1 , str[l - 1 ] - 97 + 1 );
str[l - 1 ] = ( char )x;
update(tree, l, 1 , str[l - 1 ] - 97 + 1 );
}
static void qType2( int tree[][], int l, int r, char str[])
{
int count = 0 ;
for ( int i = 1 ; i <= 26 ; i++) {
if (l == 1 ) {
if (getFrequency(tree, r, i) % 2 == 1 )
count++;
}
else {
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" );
}
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 );
}
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);
}
}
|
Python3
max = 1000 ;
def getFrequency(tree, idx, i):
sum = 0 ;
while (idx > 0 ):
sum + = tree[idx][i];
idx - = (idx & - idx);
return sum ;
def update(tree, idx, val, i):
while (idx < = max ):
tree[idx][i] + = val;
idx + = (idx & - idx);
def qType1(tree, l, x, str1):
update(tree, l, - 1 , ord (str1[l - 1 ]) - 97 + 1 );
list1 = list (str1)
list1[l - 1 ] = x;
str1 = ''.join(list1);
update(tree, l, 1 , ord (str1[l - 1 ]) - 97 + 1 );
def qType2(tree, l, r, str1):
count = 0 ;
for i in range ( 1 , 27 ):
if (l = = 1 ):
if (getFrequency(tree, r, i) % 2 = = 1 ):
count + = 1 ;
else :
if ((getFrequency(tree, r, i) -
getFrequency(tree, l - 1 , i)) % 2 = = 1 ):
count + = 1 ;
print ( "Yes" ) if (count < = 1 ) else print ( "No" );
def buildBIT(tree,str1, n):
for i in range (n):
update(tree, i + 1 , 1 , ord (str1[i]) - 97 + 1 );
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);
|
C#
using System;
class GFG
{
static int max = 1000;
static int getFrequency( int [,]tree, int idx, int i)
{
int sum = 0;
while (idx > 0)
{
sum += tree[idx,i];
idx -= (idx & -idx);
}
return sum;
}
static void update( int [,]tree, int idx,
int val, int i)
{
while (idx <= max)
{
tree[idx,i] += val;
idx += (idx & -idx);
}
}
static void qType1( int [,]tree, int l, int x, char []str)
{
update(tree, l, -1, str[l - 1] - 97 + 1);
str[l - 1] = ( char )x;
update(tree, l, 1, str[l - 1] - 97 + 1);
}
static void qType2( int [,]tree, int l, int r, char []str)
{
int count = 0;
for ( int i = 1; i <= 26; i++)
{
if (l == 1)
{
if (getFrequency(tree, r, i) % 2 == 1)
count++;
}
else
{
if ((getFrequency(tree, r, i) - getFrequency(tree, l - 1, i)) % 2 == 1)
count++;
}
}
if (count <= 1)
Console.WriteLine( "Yes" );
else
Console.WriteLine( "No" );
}
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);
}
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);
}
}
|
Javascript
<script>
let max = 1000;
function getFrequency(tree,idx,i)
{
let sum = 0;
while (idx > 0) {
sum += tree[idx][i];
idx -= (idx & -idx);
}
return sum;
}
function update(tree,idx,val,i)
{
while (idx <= max) {
tree[idx][i] += val;
idx += (idx & -idx);
}
}
function qType1(tree,l,x,str)
{
update(tree, l, -1,
str[l - 1].charCodeAt(0) - 97 + 1);
str[l - 1] = x;
update(tree, l, 1,
str[l - 1].charCodeAt(0) - 97 + 1);
}
function qType2(tree,l,r,str)
{
let count = 0;
for (let i = 1; i <= 26; i++) {
if (l == 1) {
if (getFrequency(tree, r, i) % 2 == 1)
count++;
}
else {
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>" );
}
function buildBIT(tree,str,n)
{
for (let i = 0; i < n; i++)
update(tree, i + 1, 1,
str[i].charCodeAt(0) - 97 + 1);
}
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);
</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)
This article is contributed byAnuj Chauhan. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.