Minimum length of the sub-string whose characters can be used to form a palindrome of length K

Given a string str consisting of lowercase English letters and an integer K. The task is to find the minimum length of the sub-string whose characters can be used to form a palindrome of length K. If no such sub-string exists then print -1.

Examples:

Input: str = “abcda”, k = 2
Output: 5
In order to form a palindrome of length 2, both the occurrences of ‘a’ are required.
Hence, the length of the required sub-string will be 5.

Input: str = “abcde”, k = 5
Output: -1
No palindromic string of length 5 can be formed from the characters of the given string.

Approach: The idea is to use Binary Search. Minimum character needed to form a palindrome of length K is K. So, our search domain gets reduced to [K, length(str)]. Apply binary search in this range and find a sub-string of length X (K ≤ X ≤ length(S)) such that using some or all characters of this sub-string a palindromic string of size K can be formed. Minimum X which satisfies the given condition will be the required answer. If no such such sub-string is possible then print -1.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
  
// Function that returns true if
// a palindrome can be formed using
// exactly k characters
bool isPalindrome(int freq[], int k)
{
    // Variable to check if characters
    // with odd frequency are present
    int flag = 0;
  
    // Variable to store maximum length
    // of the palindrome that can be formed
    int length = 0;
  
    for (int i = 0; i < 26; i++) {
        if (freq[i] == 0)
            continue;
  
        else if (freq[i] == 1)
            flag = 1;
  
        else {
            if (freq[i] & 1)
                flag = 1;
            length += freq[i] / 2;
        }
    }
  
    // If k is odd
    if (k & 1) {
        if (2 * length + flag >= k)
            return true;
    }
  
    // If k is even
    else {
        if (2 * length >= k)
            return true;
    }
  
    // If palindrome of length
    // k cant be formed
    return false;
}
  
// Function that returns true if a palindrome
// of length k can be formed from a
// sub-string of length m
bool check(string str, int m, int k)
{
    // Stores frequency of characters
    // of a substring of length m
    int freq[26] = { 0 };
  
    for (int i = 0; i < m; i++)
        freq[str[i] - 'a']++;
  
    // If a palindrome can be
    // formed from a substring of
    // length m
    if (isPalindrome(freq, k))
        return true;
  
    // Check for all the substrings of
    // length m, if a palindrome of
    // length k can be formed
    for (int i = m; i < str.length(); i++) {
        freq[str[i - m] - 'a']--;
        freq[str[i] - 'a']++;
  
        if (isPalindrome(freq, k))
            return true;
    }
  
    // If no palindrome of length
    // k can be formed
    return false;
}
  
// Function to return the minimum length
// of the sub-string whose characters can be
// used to form a palindrome of length k
int find(string str, int n, int k)
{
    int l = k;
    int h = n;
  
    // To store the minimum length of the
    // sub-string that can be used to form
    // a palindrome of length k
    int ans = -1;
  
    while (l <= h) {
        int m = (l + h) / 2;
        if (check(str, m, k)) {
            ans = m;
            h = m - 1;
        }
        else
            l = m + 1;
    }
  
    return ans;
}
  
// Driver code
int main()
{
    string str = "abcda";
    int n = str.length();
    int k = 2;
    cout << find(str, n, k);
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java implementation of the approach
import java.util.*;
  
class GFG 
{
  
// Function that returns true if
// a palindrome can be formed using
// exactly k characters
static boolean isPalindrome(int freq[], int k)
{
    // Variable to check if characters
    // with odd frequency are present
    int flag = 0;
  
    // Variable to store maximum length
    // of the palindrome that can be formed
    int length = 0;
  
    for (int i = 0; i < 26; i++) 
    {
        if (freq[i] == 0)
            continue;
  
        else if (freq[i] == 1)
            flag = 1;
  
        else 
        {
            if (freq[i] % 2 == 1)
                flag = 1;
            length += freq[i] / 2;
        }
    }
  
    // If k is odd
    if (k % 2 == 1)
    {
        if (2 * length + flag >= k)
            return true;
    }
  
    // If k is even
    else 
    {
        if (2 * length >= k)
            return true;
    }
  
    // If palindrome of length
    // k cant be formed
    return false;
}
  
// Function that returns true if a palindrome
// of length k can be formed from a
// sub-string of length m
static boolean check(String str, int m, int k)
{
    // Stores frequency of characters
    // of a substring of length m
    int []freq = new int[26];
  
    for (int i = 0; i < m; i++)
        freq[str.charAt(i) - 'a']++;
  
    // If a palindrome can be
    // formed from a substring of
    // length m
    if (isPalindrome(freq, k))
        return true;
  
    // Check for all the substrings of
    // length m, if a palindrome of
    // length k can be formed
    for (int i = m; i < str.length(); i++)
    {
        freq[str.charAt(i-m) - 'a']--;
        freq[str.charAt(i) - 'a']++;
  
        if (isPalindrome(freq, k))
            return true;
    }
  
    // If no palindrome of length
    // k can be formed
    return false;
}
  
// Function to return the minimum length
// of the sub-string whose characters can be
// used to form a palindrome of length k
static int find(String str, int n, int k)
{
    int l = k;
    int h = n;
  
    // To store the minimum length of the
    // sub-string that can be used to form
    // a palindrome of length k
    int ans = -1;
  
    while (l <= h) 
    {
        int m = (l + h) / 2;
        if (check(str, m, k)) 
        {
            ans = m;
            h = m - 1;
        }
        else
            l = m + 1;
    }
  
    return ans;
}
  
// Driver code
public static void main(String[] args)
{
    String str = "abcda";
    int n = str.length();
    int k = 2;
    System.out.println(find(str, n, k));
    }
}
  
// This code is contributed by Rajput-Ji

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python 3 implementation of the approach
  
# Function that returns true if
# a palindrome can be formed using
# exactly k characters
def isPalindrome(freq, k): 
      
    # Variable to check if characters
    # with odd frequency are present
    flag = 0
  
    # Variable to store maximum length
    # of the palindrome that can be formed
    length = 0
  
    for i in range(26):
        if (freq[i] == 0):
            continue
  
        elif (freq[i] == 1):
            flag = 1
  
        else:
            if (freq[i] & 1):
                flag = 1
            length += freq[i] // 2
  
    # If k is odd
    if (k & 1):
        if (2 * length + flag >= k):
            return True
  
    # If k is even
    else:
        if (2 * length >= k):
            return True
  
    # If palindrome of length
    # k cant be formed
    return False
  
# Function that returns true if a palindrome
# of length k can be formed from a
# sub-string of length m
def check(str, m, k):
      
    # Stores frequency of characters
    # of a substring of length m
    freq = [0 for i in range(26)] 
  
    for i in range(m):
        freq[ord(str[i]) - ord('a')] += 1
  
    # If a palindrome can be
    # formed from a substring of
    # length m
    if (isPalindrome(freq, k)):
        return True
  
    # Check for all the substrings of
    # length m, if a palindrome of
    # length k can be formed
    for i in range(m, len(str), 1):
        freq[ord(str[i - m]) - ord('a')] -= 1
        freq[ord(str[i]) - ord('a')] += 1
  
        if (isPalindrome(freq, k)):
            return True
  
    # If no palindrome of length
    # k can be formed
    return False
  
# Function to return the minimum length
# of the sub-string whose characters can be
# used to form a palindrome of length k
def find(str, n, k):
    l = k
    h = n
  
    # To store the minimum length of the
    # sub-string that can be used to form
    # a palindrome of length k
    ans = -1
  
    while (l <= h):
        m = (l + h) // 2
        if (check(str, m, k)):
            ans = m
            h = m - 1
          
        else:
            l = m + 1
  
    return ans
  
# Driver code
if __name__ == '__main__':
    str = "abcda"
    n = len(str)
    k = 2
    print(find(str, n, k))
  
# This code is contributed by
# Surendra_Gangwar

chevron_right


C#

// C# implementation of the approach
using System;

class GFG
{

// Function that returns true if
// a palindrome can be formed using
// exactly k characters
static Boolean isPalindrome(int []freq, int k)
{
// Variable to check if characters
// with odd frequency are present
int flag = 0;

// Variable to store maximum length
// of the palindrome that can be formed
int length = 0;

for (int i = 0; i < 26; i++) { if (freq[i] == 0) continue; else if (freq[i] == 1) flag = 1; else { if (freq[i] % 2 == 1) flag = 1; length += freq[i] / 2; } } // If k is odd if (k % 2 == 1) { if (2 * length + flag >= k)
return true;
}

// If k is even
else
{
if (2 * length >= k)
return true;
}

// If palindrome of length
// k cant be formed
return false;
}

// Function that returns true if a palindrome
// of length k can be formed from a
// sub-string of length m
static Boolean check(String str, int m, int k)
{
// Stores frequency of characters
// of a substring of length m
int []freq = new int[26];

for (int i = 0; i < m; i++) freq[str[i] - 'a']++; // If a palindrome can be // formed from a substring of // length m if (isPalindrome(freq, k)) return true; // Check for all the substrings of // length m, if a palindrome of // length k can be formed for (int i = m; i < str.Length; i++) { freq[str[i - m] - 'a']--; freq[str[i] - 'a']++; if (isPalindrome(freq, k)) return true; } // If no palindrome of length // k can be formed return false; } // Function to return the minimum length // of the sub-string whose characters can be // used to form a palindrome of length k static int find(String str, int n, int k) { int l = k; int h = n; // To store the minimum length of the // sub-string that can be used to form // a palindrome of length k int ans = -1; while (l <= h) { int m = (l + h) / 2; if (check(str, m, k)) { ans = m; h = m - 1; } else l = m + 1; } return ans; } // Driver code public static void Main(String[] args) { String str = "abcda"; int n = str.Length; int k = 2; Console.WriteLine(find(str, n, k)); } } // This code is contributed by PrinciRaj1992 [tabby title = "PHP"]

filter_none

edit
close

play_arrow

link
brightness_4
code

<?php
// PHP implementation of the approach 
  
// Function that returns true if 
// a palindrome can be formed using 
// exactly k characters 
function isPalindrome($freq, $k
    // Variable to check if characters 
    // with odd frequency are present 
    $flag = 0; 
  
    // Variable to store maximum length 
    // of the palindrome that can be formed 
    $length = 0; 
  
    for ($i = 0; $i < 26; $i++) 
    
        if ($freq[$i] == 0) 
            continue
  
        else if ($freq[$i] == 1) 
            $flag = 1; 
  
        else 
        
            if ($freq[$i] & 1) 
                $flag = 1; 
                  
            $length += floor($freq[$i] / 2); 
        
    
  
    // If k is odd 
    if ($k & 1)
    
        if (2 * $length + $flag >= $k
            return true; 
    
  
    // If k is even 
    else 
    
        if (2 * $length >= $k
            return true; 
    
  
    // If palindrome of length 
    // k cant be formed 
    return false; 
  
// Function that returns true if a palindrome 
// of length k can be formed from a 
// sub-string of length m 
function check($str, $m, $k
    // Stores frequency of characters 
    // of a substring of length m 
    $freq = array_fill(0, 26, 0); 
  
    for ($i = 0; $i < $m; $i++) 
        $freq[ord($str[$i]) - ord('a')]++; 
  
    // If a palindrome can be 
    // formed from a substring of 
    // length m 
    if (isPalindrome($freq, $k)) 
        return true; 
  
    // Check for all the substrings of 
    // length m, if a palindrome of 
    // length k can be formed 
    for ($i = $m; $i < strlen($str); $i++)
    {
        $freq[ord($str[$i - $m]) - ord('a')] -= 1; 
        $freq[ord($str[$i]) - ord('a')] += 1; 
  
        if (isPalindrome($freq, $k)) 
            return true; 
    
  
    // If no palindrome of length 
    // k can be formed 
    return false; 
  
// Function to return the minimum length 
// of the sub-string whose characters can be 
// used to form a palindrome of length k 
function find($str, $n, $k
    $l = $k
    $h = $n
  
    // To store the minimum length of the 
    // sub-string that can be used to form 
    // a palindrome of length k 
    $ans = -1; 
  
    while ($l <= $h
    
        $m = floor(($l + $h) / 2); 
        if (check($str, $m, $k))
        
            $ans = $m
            $h = $m - 1; 
        
        else
            $l = $m + 1; 
    
  
    return $ans
  
// Driver code 
$str = "abcda"
$n = strlen($str); 
$k = 2; 
  
echo find($str, $n, $k); 
  
// This code is improved by Ryuga
?>

chevron_right


Output:

5


My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.