用最小的变化制作一个字典最小的回文
给定一个字符串S。打印可能的字典最小字符串。您可以对字符串中的字符进行最少的更改,并且可以置换字符串。
例子:
Input : S = "aabc"
Output : "abba"
Input : S = "äabcd"
Output : "abcba"
解释1:将最后一个索引“c”改为“b”,变为“aabb”。然后重新排列字符串,它变成了“abba”。这是字典上最小的字符串。
解释2:将“d”改为“b”=>“aabcb”=>“abcba”。
方法:
cnt[a] 是字符a 的出现次数。考虑 cnt[a] 的奇数值,则回文不能包含多个带有 cnt[a] 的字符a。表示奇数 cnt[] 的字符如下 a 1 , a 2 .... ak (按字母顺序)。将任何符号 a k替换为1 ,将k-1替换为2 ,依此类推,直到上述序列的中间。现在,奇数符号不超过一个。把它放在答案的中间。答案的前半部分将包括符号 a 的出现。下半部分将包含相反顺序的相同符号。
例子 :
take string S = "aabcd"
cnt[a] = 2, cnt[b] = 1, cnt = 1, cnt[d] = 1.
Odd characters => b, c, d
replace ak('d') with a1('b') we get => b, c, b.
cnt[b] = 2, cnt = 1.Place odd character in middle
and 'a' and 'b' in first half and also in second half,
we get "abcba".
C++
// CPP code for changing a string
// into lexicographically smallest
// pallindromic string
#include
using namespace std;
// Function to create a palindrome
int Palindrome(string s, int n)
{
unordered_map cnt;
string R = "";
// Count the occurrences of
// every character in the string
for (int i = 0; i < n; i++) {
char a = s[i];
cnt[a]++;
}
// Create a string of characters
// with odd occurrences
for (char i = 'a'; i <= 'z'; i++) {
if (cnt[i] % 2 != 0)
R += i;
}
int l = R.length();
int j = 0;
// Change the created string upto
// middle element and update
// count to make sure that only
// one odd character exists.
for (int i = l - 1; i >= l / 2; i--) {
// decrease the count of
// character updated
cnt[R[i]]--;
R[i] = R[j];
cnt[R[j]]++;
j++;
}
// Create three strings to make
// first half second half and
// middle one.
string first, middle, second;
for (char i = 'a'; i <= 'z'; i++) {
if (cnt[i] != 0) {
// characters with even occurrences
if (cnt[i] % 2 == 0) {
int j = 0;
// fill the first half.
while (j < cnt[i] / 2) {
first += i;
j++;
}
}
// character with odd occurrence
else {
int j = 0;
// fill the first half with
// half of occurrence except one
while (j < (cnt[i] - 1) / 2) {
first += i;
j++;
}
// For middle element
middle += i;
}
}
}
// create the second half by
// reversing the first half.
second = first;
reverse(second.begin(), second.end());
string resultant = first + middle + second;
cout << resultant << endl;
}
// Driver code
int main()
{
string S = "geeksforgeeks";
int n = S.length();
Palindrome(S, n);
return 0;
}
Python3
# Python code for changing a string
# into lexicographically smallest
# pallindromic string
# Function to create a palindrome
def palindrome(s: str, n: int) -> int:
cnt = dict()
R = []
# Count the occurrences of
# every character in the string
for i in range(n):
a = s[i]
if a in cnt:
cnt[a] += 1
else:
cnt[a] = 1
# Create a string of characters
# with odd occurrences
i = 'a'
while i <= 'z':
if i in cnt and cnt[i] % 2 != 0:
R += i
i = chr(ord(i) + 1)
l = len(R)
j = 0
# Change the created string upto
# middle element and update
# count to make sure that only
# one odd character exists.
for i in range(l - 1, (l // 2) - 1, -1):
# decrease the count of
# character updated
if R[i] in cnt:
cnt[R[i]] -= 1
else:
cnt[R[i]] = -1
R[i] = R[j]
if R[j] in cnt:
cnt[R[j]] += 1
else:
cnt[R[j]] = 1
j += 1
# Create three strings to make
# first half second half and
# middle one.
first, middle, second = "", "", ""
i = 'a'
while i <= 'z':
if i in cnt:
# characters with even occurrences
if cnt[i] % 2 == 0:
j = 0
# fill the first half.
while j < cnt[i] // 2:
first += i
j += 1
# character with odd occurrence
else:
j = 0
# fill the first half with
# half of occurrence except one
while j < (cnt[i] - 1) // 2:
first += i
j += 1
# For middle element
middle += i
i = chr(ord(i) + 1)
# create the second half by
# reversing the first half.
second = first
second = ''.join(reversed(second))
resultant = first + middle + second
print(resultant)
# Driver Code
if __name__ == "__main__":
S = "geeksforgeeks"
n = len(S)
palindrome(S, n)
# This code is contributed by
# sanjeev2552
输出:
eefgksoskgfee