Open In App

Queries on substring palindrome formation

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 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 Programint 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 Codestr1 = "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



Javascript



Output

Yes
Yes
No

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 #define max 1000using 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 BITvoid 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 palindromevoid 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 alphabetvoid 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 Programint 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 BITdef 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 palindromedef 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 alphabetdef 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



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.