给定两个字符串S和P ,任务是通过重新排列字符后从给定的字符串S和P中选择字符来找到最大的回文字符串。
注意:如果可能有许多答案,请在词典上找到具有最大长度的最小T。
例子:
Input: S = “abad”, T = “eeff”
Output: aefbfea
Explanation:
From the first string “aba” and from the second string “effe” are palindromes.
Use these two to make a new palindrome T “aefbfea” which is lexicographically smallest.
Also T is of maximum length possible.
Note: “ada”, although this will give T of same length i.e., 7 but that won’t be lexicographically smallest.
Input: S = “aeabb”, T = “dfedf”
Output: abdeffedba
Explanation:
From the first string “abeba” and from the second string “dfefd”, are palindrome. Combine the two to get T: “abdeffedba” is lexicographically smallest.
方法:我们的想法是采取一切与字符串S和P中存在甚至多次分别的字符。作为子字符串,两个字符串的A和B都具有在S和P中出现偶数次的所有字符,从而成为父字符串最大的回文。步骤如下:
- 从字符串S和P中选取一个字符,这样它们将分别出现在从每个字符串取出的回文中。将唯一元素放在T的中间。
- 从子字符串A和B中获取唯一元素的可能情况是:
- 如果在A和B中都存在一个唯一元素,则应同时使用它们,因为这会使T的长度增加2 。
- 如果在S和P中都存在唯一元素,但不存在相同元素,则采用较小的元素,因为这将使字典上的最小回文数T最小。
- 如果两者均不存在唯一元素,则仅使用A和B中的元素构成字符串T。
- 使用无序映射可以计算在父字符串偶数次出现的字符数。另外,使用另一个映射来计算要使用的字符数T。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find largest palindrome
// possible from S and P after rearranging
// characters to make palindromic string T
string mergePalindromes(string S, string P)
{
// Using unordered_map to store
// frequency of elements
// mapT will have freq of elements of T
unordered_map mapS, mapP, mapT;
// Size of both the strings
int n = S.size(), m = P.size();
for (int i = 0; i < n; i++) {
mapS[S[i]]++;
}
for (int i = 0; i < m; i++) {
mapP[P[i]]++;
}
// Take all character in mapT which
// occur even number of times in
// respective strings & simultaneously
// update number of characters left in map
for (char i = 'a'; i <= 'z'; i++) {
if (mapS[i] % 2 == 0) {
mapT[i] += mapS[i];
mapS[i] = 0;
}
else {
mapT[i] += mapS[i] - 1;
mapS[i] = 1;
}
if (mapP[i] % 2 == 0) {
mapT[i] += mapP[i];
mapP[i] = 0;
}
else {
mapT[i] += mapP[i] - 1;
mapP[i] = 1;
}
}
// Check if a unique character is
// present in both string S and P
int check = 0;
for (char i = 'a'; i <= 'z'; i++) {
if (mapS[i] > 0 && mapP[i] > 0) {
mapT[i] += 2;
check = 1;
break;
}
}
// Making string T in two halves
// half1 - first half
// half2 - second half
string half1 = "", half2 = "";
for (char i = 'a'; i <= 'z'; i++) {
for (int j = 0; (2 * j) < mapT[i]; j++) {
half1 += i;
half2 += i;
}
}
// Reverse the half2 to attach with half1
// to make palindrome T
reverse(half2.begin(), half2.end());
// If same unique element is present
// in both S and P, then taking that only
// which is already taken through mapT
if (check) {
return half1 + half2;
}
// If same unique element is not
// present in S and P, then take
// characters that make string T
// lexicographically smallest
for (char i = 'a'; i <= 'z'; i++) {
if (mapS[i] > 0 || mapP[i] > 0) {
half1 += i;
return half1 + half2;
}
}
// If no unique element is
// present in both string S and P
return half1 + half2;
}
// Driver Code
int main()
{
// Given two strings S and P
string S = "aeabb";
string P = "dfedf";
// Function Call
cout << mergePalindromes(S, P);
return 0;
}
Java
// Java program for the above approach
import java.util.*;
import java.lang.*;
class GFG{
// Function to find largest palindrome
// possible from S and P after rearranging
// characters to make palindromic string T
static String mergePalindromes(StringBuilder S,
StringBuilder P)
{
// Using unordered_map to store
// frequency of elements
// mapT will have freq of elements of T
Map mapS = new HashMap<>(),
mapP = new HashMap<>(),
mapT = new HashMap<>();
// Size of both the strings
int n = S.length(), m = P.length();
for(int i = 0; i < n; i++)
{
mapS.put(S.charAt(i),
mapS.getOrDefault(S.charAt(i), 0) + 1);
}
for(int i = 0; i < m; i++)
{
mapP.put(P.charAt(i),
mapP.getOrDefault(P.charAt(i), 0) + 1);
}
// Take all character in mapT which
// occur even number of times in
// respective strings & simultaneously
// update number of characters left in map
for(char i = 'a'; i <= 'z'; i++)
{
if (mapS.getOrDefault(i, 0) % 2 == 0)
{
mapT.put(i,mapT.getOrDefault(i, 0) +
mapS.getOrDefault(i, 0));
mapS.put(i, 0);
}
else
{
mapT.put(i,mapT.getOrDefault(i, 0) +
mapS.getOrDefault(i, 0) - 1);
mapS.put(i, 1);
}
if (mapP.getOrDefault(i, 0) % 2 == 0)
{
mapT.put(i, mapT.getOrDefault(i, 0) +
mapP.getOrDefault(i, 0));
mapP.put(i, 0);
}
else
{
mapT.put(i, mapT.getOrDefault(i, 0) +
mapP.getOrDefault(i, 0) - 1);
mapP.put(i, 1);
}
}
// Check if a unique character is
// present in both string S and P
int check = 0;
for(char i = 'a'; i <= 'z'; i++)
{
if (mapS.getOrDefault(i, 0) > 0 &&
mapP.getOrDefault(i, 0) > 0)
{
mapT.put(i, mapT.getOrDefault(i, 0) + 2);
check = 1;
break;
}
}
// Making string T in two halves
// half1 - first half
// half2 - second half
StringBuilder half1 = new StringBuilder(),
half2 = new StringBuilder();
for(char i = 'a'; i <= 'z'; i++)
{
for(int j = 0;
(2 * j) < mapT.getOrDefault(i, 0);
j++)
{
half1.append(i);
half2.append(i);
}
}
// Reverse the half2 to attach with half1
// to make palindrome T
StringBuilder tmp = half2.reverse();
// If same unique element is present
// in both S and P, then taking that only
// which is already taken through mapT
if (check == 1)
{
return half1.append(tmp).toString();
}
// If same unique element is not
// present in S and P, then take
// characters that make string T
// lexicographically smallest
for(char i = 'a'; i <= 'z'; i++)
{
if (mapS.getOrDefault(i, 0) > 0 ||
mapP.getOrDefault(i, 0) > 0)
{
half1.append(i);
return half1.append(tmp).toString();
}
}
// If no unique element is
// present in both string S and P
return half1.append(tmp).toString();
}
// Driver code
public static void main (String[] args)
{
// Given two strings S and P
StringBuilder S = new StringBuilder("aeabb");
StringBuilder P = new StringBuilder("dfedf");
// Function call
System.out.println(mergePalindromes(S, P));
}
}
// This code is contributed by offbeat
Python3
# Python3 program for the above approach
from collections import defaultdict
# Function to find largest palindrome
# possible from S and P after rearranging
# characters to make palindromic string T
def mergePalindromes(S, P):
# Using unordered_map to store
# frequency of elements
# mapT will have freq of elements of T
mapS = defaultdict(lambda : 0)
mapP = defaultdict(lambda : 0)
mapT = defaultdict(lambda : 0)
# Size of both the strings
n = len(S)
m = len(P)
for i in range(n):
mapS[ord(S[i])] += 1
for i in range(m):
mapP[ord(P[i])] += 1
# Take all character in mapT which
# occur even number of times in
# respective strings & simultaneously
# update number of characters left in map
for i in range(ord('a'), ord('z') + 1):
if(mapS[i] % 2 == 0):
mapT[i] += mapS[i]
mapS[i] = 0
else:
mapT[i] += mapS[i] - 1
mapS[i] = 1
if (mapP[i] % 2 == 0):
mapT[i] += mapP[i]
mapP[i] = 0
else:
mapT[i] += mapP[i] - 1
mapP[i] = 1
# Check if a unique character is
# present in both string S and P
check = 0
for i in range(ord('a'), ord('z') + 1):
if (mapS[i] > 0 and mapP[i] > 0):
mapT[i] += 2
check = 1
break
# Making string T in two halves
# half1 - first half
# half2 - second half
half1, half2 = "", ""
for i in range(ord('a'), ord('z') + 1):
j = 0
while((2 * j) < mapT[i]):
half1 += chr(i)
half2 += chr(i)
j += 1
# Reverse the half2 to attach with half1
# to make palindrome
half2 = half2[::-1]
# If same unique element is present
# in both S and P, then taking that only
# which is already taken through mapT
if(check):
return half1 + half2
# If same unique element is not
# present in S and P, then take
# characters that make string T
# lexicographically smallest
for i in range(ord('a'), ord('z') + 1):
if(mapS[i] > 0 or mapP[i] > 0):
half1 += chr(i)
return half1 + half2
# If no unique element is
# present in both string S and P
return half1 + half2
# Driver Code
# Given string S and P
S = "aeabb"
P = "dfedf"
# Function call
print(mergePalindromes(S, P))
# This code is contributed by Shivam Singh
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
using System.Text;
class GFG{
// Function to find largest palindrome
// possible from S and P after rearranging
// characters to make palindromic string T
static string mergePalindromes(string S,
string P)
{
// Using unordered_map to store
// frequency of elements mapT will
// have freq of elements of T
Dictionary mapS = new Dictionary();
Dictionary mapP = new Dictionary();
Dictionary mapT = new Dictionary();
// Size of both the strings
int n = S.Length, m = P.Length;
for(char i = 'a'; i <= 'z'; i++)
{
mapS[i] = 0;
mapP[i] = 0;
mapT[i] = 0;
}
for(int i = 0; i < n; i++)
{
mapS[S[i]]++;
}
for(int i = 0; i < m; i++)
{
mapP[P[i]]++;
}
// Take all character in mapT which
// occur even number of times in
// respective strings & simultaneously
// update number of characters left in map
for(char i = 'a'; i <= 'z'; i++)
{
if (mapS[i] % 2 == 0)
{
mapT[i] += mapS[i];
mapS[i] = 0;
}
else
{
mapT[i] += mapS[i] - 1;
mapS[i] = 1;
}
if (mapP[i] % 2 == 0)
{
mapT[i] += mapP[i];
mapP[i] = 0;
}
else
{
mapT[i] += mapP[i] - 1;
mapP[i] = 1;
}
}
// Check if a unique character is
// present in both string S and P
int check = 0;
for(char i = 'a'; i <= 'z'; i++)
{
if (mapS[i] > 0 && mapP[i] > 0)
{
mapT[i] += 2;
check = 1;
break;
}
}
// Making string T in two halves
// half1 - first half
// half2 - second half
string half1 = "", half2 = "";
for(char i = 'a'; i <= 'z'; i++)
{
for(int j = 0; (2 * j) < mapT[i]; j++)
{
half1 += i;
half2 += i;
}
}
// Reverse the half2 to attach with half1
// to make palindrome T
char[] tmp = half2.ToCharArray();
Array.Reverse(tmp);
half2 = new string(tmp);
// If same unique element is present
// in both S and P, then taking that only
// which is already taken through mapT
if (check != 0)
{
return half1 + half2;
}
// If same unique element is not
// present in S and P, then take
// characters that make string T
// lexicographically smallest
for(char i = 'a'; i <= 'z'; i++)
{
if (mapS[i] > 0 || mapP[i] > 0)
{
half1 += i;
return half1 + half2;
}
}
// If no unique element is
// present in both string S and P
return half1 + half2;
}
// Driver Code
public static void Main(string []args)
{
// Given two strings S and P
string S = "aeabb";
string P = "dfedf";
Console.Write(mergePalindromes(S, P));
}
}
// This code is contributed by rutvik_56
abdeffedba
时间复杂度: O(N),其中N是字符串S或P的长度。
辅助空间: O(N)