Open In App

Check if a substring can be Palindromic by replacing K characters for Q queries

Last Updated : 14 Jul, 2023
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a string str and Q queries in form of [L, R, K], the task is to find whether characters from the string from [L, R] with at most K changes are allowed can be rearranged to make string palindromic or not. For each query, print "YES" if it can become a palindromic string else print "NO".
Examples: 

Input: str = "GeeksforGeeks", Q = { { 1, 5, 3 }, { 5, 7, 0 }, { 8, 11, 3 }, {3, 10, 5 }, { 0, 9, 5 } } 
Output: 
YES 
NO 
YES 
YES 
YES 
Explanation: 
queries[0] : substring = "eeksf", could be changed to "eekee" which is palindrome. 
queries[1] : substring = "for", is not palindrome and can't be made palindromic after replacing atmost 0 character.. 
queries[2] : substring = "Geek", could be changed to "GeeG" which is palindrome. 
queries[3] : substring = "ksforGee", could be changed to "ksfoofsk" which is palindrome. 
queries[4] : substring = "GeeksforGe", could be changed to "GeeksskeeG" which is palindrome.
Input: str = "abczwerte", Q = { { 3, 7, 4 }, { 1, 8, 10 }, { 0, 3, 1 } } 
Output: 
YES 
YES 
NO 

Approach: This problem can be solved using Dynamic Programming.  

  • Create a 2D matrix (say dp[i][j]) where dp[i][j] denotes the count of ith character in the substring str[0...j].
  • Below is the recurrence relation for the above approach: 
    • If str[i] is equals to str[j], then dp[i][j] = 1 + dp[i][j-1].
    • If str[i] is not equals to str[j], then dp[i][j] = dp[i][j-1].
    • if j equals 0, then dp[i][j] would be one of the first characters which are equal to ith characters.
  • For each query, find out the count of each character in the substring str[L...R] by the simple relation:
count =  dp[i][right] - dp[i][left] + (str[left] == i + 'a').
  • Get the count of unmatched pairs.
  • Now we need to convert the half unmatched characters to the remaining characters. If the count of half unmatched characters is less than or equals to K then, print "YES" else print "NO".

Below is the implementation of the above approach: 
 

C++
// C++ program for the above approach

#include <bits/stdc++.h>
using namespace std;

// Function to find whether string can
// be made palindromic or not for each queries
void canMakePaliQueries(
    string str,
    vector<vector<int> >& Q)
{
    int n = str.length();

    // To store the count of ith character
    // of substring str[0...i]
    vector<vector<int> > dp(
        26,
        vector<int>(n, 0));

    for (int i = 0; i < 26; i++) {

        // Current character
        char currentChar = i + 'a';
        for (int j = 0; j < n; j++) {

            // Update dp[][] on the basis
            // recurrence relation
            if (j == 0) {
                dp[i][j]
                    = (str[j] == currentChar);
            }
            else {
                dp[i][j]
                    = dp[i][j - 1]
                      + (str[j] == currentChar);
            }
        }
    }

    // For each queries
    for (auto query : Q) {
        int left = query[0];
        int right = query[1];
        int k = query[2];

        // To store the count of
        // distinct character
        int unMatchedCount = 0;
        for (int i = 0; i < 26; i++) {

            // Find occurrence of i + 'a'
            int occurrence
                = dp[i][right]
                  - dp[i][left]
                  + (str[left] == (i + 'a'));

            if (occurrence & 1)
                unMatchedCount++;
        }

        // Half the distinct Count
        int ans = unMatchedCount / 2;

        // If half the distinct count is
        // less than equals to K then
        // palindromic string can be made
        if (ans <= k) {
            cout << "YES\n";
        }
        else {
            cout << "NO\n";
        }
    }
}

// Driver Code
int main()
{
    // Given string str
    string str = "GeeksforGeeks";

    // Given Queries
    vector<vector<int> > Q;
    Q = { { 1, 5, 3 }, { 5, 7, 0 },
 { 8, 11, 3 }, { 3, 10, 5 }, 
{ 0, 9, 5 } };

    // Function call
    canMakePaliQueries(str, Q);
    return 0;
}
Java
// Java program for the above approach
class GFG{

// Function to find whether String can be 
// made palindromic or not for each queries
static void canMakePaliQueries(String str, 
                               int [][]Q)
{
    int n = str.length();

    // To store the count of ith character
    // of subString str[0...i]
    int [][]dp = new int[26][n];

    for(int i = 0; i < 26; i++)
    {
       
       // Current character
       char currentChar = (char)(i + 'a');
       for(int j = 0; j < n; j++)
       {
       
          // Update dp[][] on the basis
          // recurrence relation
          if (j == 0)
          {
              dp[i][j] = (str.charAt(j) == 
                          currentChar) ? 1 : 0;
          }
          else
          {
              dp[i][j] = dp[i][j - 1] +
                         ((str.charAt(j) == 
                           currentChar) ? 1 : 0);
          }
       }
    }

    // For each queries
    for(int []query : Q)
    {
       int left = query[0];
       int right = query[1];
       int k = query[2];
       
       // To store the count of
       // distinct character
       int unMatchedCount = 0;
       for(int i = 0; i < 26; i++)
       {
           
          // Find occurrence of i + 'a'
          int occurrence = dp[i][right] - 
                           dp[i][left] + 
                           (str.charAt(left) == 
                           (i + 'a') ? 1 : 0);
          
          if (occurrence % 2 == 1)
              unMatchedCount++;
       }
       
       // Half the distinct Count
       int ans = unMatchedCount / 2;
       
       // If half the distinct count is
       // less than equals to K then
       // palindromic String can be made
       if (ans <= k)
       {
           System.out.print("YES\n");
       }
       else
       {
           System.out.print("NO\n");
       }
    }
}

// Driver Code
public static void main(String[] args)
{
    
    // Given a String str
    String str = "GeeksforGeeks";

    // Given Queries
    int [][]Q = { { 1, 5, 3 }, 
                  { 5, 7, 0 },
                  { 8, 11, 3 },
                  { 3, 10, 5 }, 
                  { 0, 9, 5 } };
                  
    // Function call
    canMakePaliQueries(str, Q);
}
}

// This code is contributed by gauravrajput1
Python3
# Python3 program for 
# the above approach

# Function to find whether 
# string can be made palindromic 
# or not for each queries 
def canMakePaliQueries(str, Q):
    n = len(str)

    # To store the count of 
    # ith character of substring 
    # str[0...i] 
    dp = [[0 for i in range(n)] 
             for j in range(26)]\
    
    for i in range(26):

        # Current character
        currentChar = chr(i + ord('a'))
        
        for j in range(n):

            # Update dp[][] on the basis 
            # recurrence relation
            if(j == 0):
                dp[i][j] = (str[j] == 
                            currentChar)
            else:
                dp[i][j] = dp[i][j - 1] + 
                           (str[j] == currentChar)

    # For each queries
    for query in Q:
        left = query[0]
        right = query[1]
        k = query[2]

        # To store the count of 
        # distinct character
        unMatchedCount = 0

        for i in range(26):

            # Find occurrence of 
            # i + 'a'
            occurrence = dp[i][right] - 
                         dp[i][left] + 
                         (str[left] == 
                          chr(i + ord('a')))
                
            if(occurrence & 1):
                unMatchedCount += 1

         # Half the distinct Count
        ans = int(unMatchedCount / 2)

        # If half the distinct count is 
        # less than equals to K then 
        # palindromic string can be made
        if(ans <= k):
            print("YES")
        else:
            print("NO")

# Driver Code

# Given string str
str = "GeeksforGeeks"

# Given Queries 
Q = [[1, 5, 3], 
     [5, 7, 0],
     [8, 11, 3], 
     [3, 10, 5],
     [0, 9, 5]]

# Function call 
canMakePaliQueries(str, Q)

# This code is contributed by avanitrachhadiya2155
C#
// C# program for the above approach
using System;
class GFG{

// Function to find whether String can be 
// made palindromic or not for each queries
static void canMakePaliQueries(String str, 
                               int [,]Q)
{
    int n = str.Length;

    // To store the count of ith character
    // of subString str[0...i]
    int [,]dp = new int[26, n];

    for(int i = 0; i < 26; i++)
    {
       
       // Current character
       char currentChar = (char)(i + 'a');
       for(int j = 0; j < n; j++)
       {
       
          // Update [,]dp on the basis
          // recurrence relation
          if (j == 0)
          {
              dp[i,j] = (str[j] == 
                         currentChar) ? 1 : 0;
          }
          else
          {
              dp[i,j] = dp[i, j - 1] +
                         ((str[j] == 
                           currentChar) ? 1 : 0);
          }
       }
    }

    // For each queries
    for(int l = 0; l < Q.GetLength(0);l++)
    {
        int []query = GetRow(Q,l);
       int left = query[0];
       int right = query[1];
       int k = query[2];
       
       // To store the count of
       // distinct character
       int unMatchedCount = 0;
       for(int i = 0; i < 26; i++)
       {
           
          // Find occurrence of i + 'a'
          int occurrence = dp[i, right] - 
                           dp[i, left] + 
                           (str[left] == 
                           (i + 'a') ? 1 : 0);
          
          if (occurrence % 2 == 1)
              unMatchedCount++;
       }
       
       // Half the distinct Count
       int ans = unMatchedCount / 2;
       
       // If half the distinct count is
       // less than equals to K then
       // palindromic String can be made
       if (ans <= k)
       {
           Console.Write("YES\n");
       }
       else
       {
           Console.Write("NO\n");
       }
    }
}
 public static int[] GetRow(int[,] matrix, int row)
  {
    var rowLength = matrix.GetLength(1);
    var rowVector = new int[rowLength];

    for (var i = 0; i < rowLength; i++)
      rowVector[i] = matrix[row, i];

    return rowVector;
  }
// Driver Code
public static void Main(String[] args)
{
    
    // Given a String str
    String str = "GeeksforGeeks";

    // Given Queries
    int [,]Q = { { 1, 5, 3 }, 
                 { 5, 7, 0 },
                 { 8, 11, 3 },
                 { 3, 10, 5 }, 
                 { 0, 9, 5 } };
                  
    // Function call
    canMakePaliQueries(str, Q);
}
}

// This code is contributed by Princi Singh 
JavaScript
<script>

// JavaScript program for the above approach

// Function to find whether String can be
// made palindromic or not for each queries
function canMakePaliQueries(str,Q)
{
    let n = str.length;
 
    // To store the count of ith character
    // of subString str[0...i]
    let dp = new Array(26);
    for(let i=0;i<26;i++)
    {
        dp[i]=new Array(n);
        for(let j=0;j<n;j++)
            dp[i][j]=0;
    }
 
    for(let i = 0; i < 26; i++)
    {
        
       // Current character
       let currentChar = String.fromCharCode(i + 'a'.charCodeAt(0));
       for(let j = 0; j < n; j++)
       {
        
          // Update dp[][] on the basis
          // recurrence relation
          if (j == 0)
          {
              dp[i][j] = (str[j] ==
                          currentChar) ? 1 : 0;
          }
          else
          {
              dp[i][j] = dp[i][j - 1] +
                         ((str[j] ==
                           currentChar) ? 1 : 0);
          }
       }
    }
 
    // For each queries
    for(let query of Q.values())
    {
       let left = query[0];
       let right = query[1];
       let k = query[2];
        
       // To store the count of
       // distinct character
       let unMatchedCount = 0;
       for(let i = 0; i < 26; i++)
       {
            
          // Find occurrence of i + 'a'
          let occurrence = dp[i][right] -
                           dp[i][left] +
                           (str[left] ==
                           (i + 'a'.charCodeAt(0)) ? 1 : 0);
           
          if (occurrence % 2 == 1)
              unMatchedCount++;
       }
        
       // Half the distinct Count
       let ans = unMatchedCount / 2;
        
       // If half the distinct count is
       // less than equals to K then
       // palindromic String can be made
       if (ans <= k)
       {
           document.write("YES<br>");
       }
       else
       {
           document.write("NO<br>");
       }
    }
}

// Driver Code


// Given a String str
let str = "GeeksforGeeks";

// Given Queries
let Q=[[ 1, 5, 3 ],
                  [ 5, 7, 0 ],
                  [ 8, 11, 3 ],
                  [ 3, 10, 5 ],
                  [ 0, 9, 5 ]];
// Function call
canMakePaliQueries(str, Q);


// This code is contributed by unknown2108

</script>

Output
YES
NO
YES
YES
YES

Time Complexity: O(26*N), where N is the length of the string. 
Auxiliary Space: O(26*N), where N is the length of the string. 


Next Article

Similar Reads