Maximize value of Palindrome by rearranging characters of a Substring


In this problem, we need to find the maximum palindromic string by rearranging the characters of any substring of the given string.

We will use bitmasking to solve the largest palindromic substring. If any substring has bitmasking 0, it contains all characters even a number of times. So, we can generate a palindromic string using the characters of that substring, and we need to find the maximum palindromic string among them.

Problem statement - We have given a string containing the N numeric characters. We need to find the maximum palindromic string by rearranging the characters of any substring of the given string.

Sample Example

Input

alpha = "81343451";

Output

4315134

Explanation - We can take the '1343451' substring and make it palindromic by rearranging its characters.

Input

alpha = "12345";

Output

5

Explanation - The maximum palindromic string that we can generate using any substring is 5.

Input

alpha = "65433456";

Output

"65433456";

Approach 1

In this approach, we will use bitmasking. We will have a binary string of length 10, and each character of the binary string represents the digits from 0 to 9. If any character's value in the binary string is '1', a related digit exists for an odd number of times in the substring.

If the bit mask contains only 1, we can choose a substring to form a palindromic substring by rearranging its character as it contains only one digit with the odd frequency.

So, we will find all such strings having bitmask 0 or containing only one '1', make them palindromic, and take maximum for an answer.

Algorithm

Step 1 - Define the list of size 1025 (210 + 1) to store the mask index and initialize the 'bitMask' with 0. Also, initialize the answer with '0' to store the maximum valid palindromic string.

Step 2 - Start traversing the string of digits.

Step 3 - Left shift 1 by character value, which can be between 0 to 9, and take XOR of its with the 'bitMask' value.

Step 4 - If 'bitMask' is 0, the substring contains all the characters with an even frequency. So, execute the maxValue() function to get the maximum palindromic string by rearranging the characters of the substring.

Step 4.1 - In the maxValue() function, define the 'freq' map to store the frequency of characters of the substring.

Step 4.2 - Initialize the 'temp' and 'odd' with the empty string.

Step 4.3 - Start traversing the map from the end. If the frequency of the character is odd, store the character in the odd. Otherwise, append freq/2 characters to the 'temp' string.

Step 4.4 - Take the reverse of the temp string.

Step 4.5 - Return the resultant string after appending the temp, odd, and reverse strings.

Step 5 - Execute the getMaximumString() function to get a maximum string from the answer and value returned by the maxValue() function.

Step 5.1 - Return the string with maximum length in the getMaximumString() function. If a string of both strings is the same, return the lexicographically the largest string.

Step 5.2 - Store the maximum string in the 'answer'.

Step 6 - We need to toggle all bits individually and get the maximum answer. So, start traversing the 0 to 9 digits.

Step 7 - In the loop, left shift the 1 by digit value, and take its XOR with the 'bitMask' value.

Step 8 - If 'newBitMask' is 0, the substring contains only 1 character with an odd frequency. So, we can rearrange substrings to make palindromic. Store the maximum substring in 'answer'.

Step 9 - If 'newBitMask' already exists in the 'index' array, take a substring from the index[newbitMask] + 1 to p index, make the maximum palindromic string, and store the maximum string in the 'answer' variable.

Step 10 - If 'bitMask' doesn't exist in the 'index' array, update its value with the 'p' index.

Step 11 - Return the 'answer'.

Example

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

// Rearrange characters to get the largest string
string maxValue(string &str, int start, int end) {
   map<char, int> freq;
   // Count frequency of each digit
   for (int p = start; p <= end; p++) {
      freq[str[p]]++;
   }
   string temp = "", odd = "";
   // Traverse map in reverse order
   for (auto iter = freq.rbegin(); iter != freq.rend(); iter++) {
      // Take 1 odd number
      if (iter->second % 2 != 0) {
         odd = iter->first;
      } else {
         temp += string(iter->second / 2, iter->first);
      }
   }
   // Reverse temp string to append it after the odd character
   string rev = temp;
   reverse(rev.begin(), rev.end());
   // Return the largest palindromic string
   return temp + odd + rev;
}
// Get maximum string
string getMaximumString(string temp1, string temp2) {
   if (temp1.size() > temp2.size())
      return temp1;
   if (temp2.size() > temp1.size())
      return temp2;
   if (temp1 > temp2) {
      return temp1;
   }
   return temp2;
}
string getMaximumPalindrome(string &alpha) {
   vector<int> index(1025, -1);
   int bitMask = 0, len = alpha.size();
   string answer = "0";
   // Iterate over the string
   for (int p = 0; p < len; p++) {
      // Toggle the bit corresponding to the digit in the bitMask
      bitMask ^= (1 << (alpha[p] - '0'));
      // When bitMask is 0, all characters appear an even number of times
      if (bitMask == 0) {
         // Get maximum palindromic string using characters from 0 to p
         answer = getMaximumString(answer, maxValue(alpha, 0, p));
      }
      // Change all bits and get a maximum answer
      for (int q = 0; q <= 9; q++) {
         // Toggle the mask
         int newbitMask = bitMask;
         newbitMask ^= (1 << q);
         // If all characters appear even a number of times
         if (newbitMask == 0) {
            answer = getMaximumString(answer, maxValue(alpha, 0, p));
         }
         // If the new mask has already visited
         else if (index[newbitMask] != -1) {
            answer = getMaximumString(answer, maxValue(alpha, index[newbitMask] + 1, p));
         }
      }
      // Updated the visited index of the mask
      if (index[bitMask] == -1) {
         index[bitMask] = p;
      }
   }
   return answer;
}
int main() {
   string alpha = "81343451";
   cout << "The maximum palindromic substring that we can create is " 
<<getMaximumPalindrome(alpha);
   return 0;
}

Output

The maximum palindromic substring that we can create is 4315134

Time complexity - O(N*N) for traversing the string and making maximum palindromic substring.

Space complexity - O(N) to store characters' frequency in the map and maximum string in the answer.

Bitmasking is a very powerful technique to make any solution efficient. If we solve the problem using the naïve approach, it takes O(N*N) time to find all substrings and O(N) times to rearrange characters of the substring. So, we solved the problem in O(N*N) time complexity instead of O(N3).

Updated on: 31-Aug-2023

81 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements