如果有多个回文,则找到最长但按字典顺序最小的回文

时间:2019-06-24 14:40:47

标签: c++ algorithm palindrome

给出一个字符串,我需要找到可以通过从字符串中删除或改组字符来构造的最长回文。如果存在多个相同长度的回文,那么我需要确保按字典顺序给出最小的回文。 示例:“ adskassda”,预期输出为:“ adsasda”

我能够找到最大的回文,但是如何确保在最大相同的最大长度的情况下,按字典顺序最小的输出作为输出?

任何回文串可以分为三部分–乞g,中音和结尾。对于奇数长度的回文字符串,例如2n + 1,“ beg”由字符串的前n个字符组成,“ mid”仅由1个字符组成,即第(n + 1)个字符,“ end”由后n个字符组成回文字符串。对于长度为2n的回文串,“ mid”将始终为空。应当注意,“ end”将与“ beg”相反,以便使字符串成为回文。 我也为此使用了相同的逻辑。

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

string longestPalindrome(string str){
    map<char,int> frequencyChar;
    for(int i=0;i<str.length();i++){
        frequencyChar[str[i]]++;
    }
    char middle_character;
    string leftStr;
    for(auto it: frequencyChar){
        char currentChar=it.first;
        int frequencyCurrentChr = it.second;
        if(frequencyCurrentChr%2!=0){
            middle_character=currentChar;
        }
        leftStr.append(frequencyCurrentChr/2,currentChar);
    }
    string rightStr(leftStr.rbegin(),leftStr.rend());
    return leftStr + middle_character + rightStr;
}
int main() {
    string str = "adskassda";
    cout<<longestPalindrome(str);
}

我正在获取“ adsssda”,但预期是“ adsasda”

3 个答案:

答案 0 :(得分:0)

这似乎对我有用,尽管我的测试还远远不够:

#include <iostream>
#include <string>
#include <map>
#include <algorithm>
using namespace std;

int main()
{
    string in("adskassda");
    map<char, int> chars;
    string out;

    for (auto c : in)
    {
        ++chars[c];
    }

    string middle;
    for (auto e : chars)
    {
        if (e.second >= 2)
        {
            out.append(e.second/2, e.first);
            e.second = e.second%2;
        }

        if (e.second && middle.empty())
            middle = e.first;
    }

    string tail(out);
    reverse(tail.begin(), tail.end());
    out = out + middle + tail;

    cout << in << endl;
    cout << out << endl;
}

答案 1 :(得分:0)

您只有一个简单的错误。当您要选择中间字符时,第一次看到具有奇数频率的字符时,就应该选择它,并且永远不要再对其进行更新,因为它将是字典顺序最低的那个。这就是为什么我添加了布尔变量mid_char_chosen并将其设置为true不会再次更新的原因。您还没有考虑另一个极端的情况:如果所有频率都是偶数,则不会有中间字符,并且结果将有偶数个字符。因此,输出应省略中间字符。经过这些小的修改,我认为代码可以运行:

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

string longestPalindrome(string str){
    map<char,int> frequencyChar;
    for(int i=0;i<str.length();i++){
        frequencyChar[str[i]]++;
    }
    char middle_character;
    string leftStr;
    bool mid_char_chosen = false;
    for(auto it: frequencyChar){
        char currentChar=it.first;
        int frequencyCurrentChr = it.second;
        if(!mid_char_chosen and frequencyCurrentChr%2!=0){
            middle_character=currentChar;
            mid_char_chosen = true;
        }
        leftStr.append(1*(frequencyCurrentChr/2),currentChar);
    }
    string rightStr(leftStr.rbegin(),leftStr.rend());
    if (mid_char_chosen)
        return leftStr + middle_character + rightStr;
    else
        return leftStr +  rightStr;
}
int main() {
    string str = "adskassda";
    cout<<longestPalindrome(str) << endl;
}

答案 2 :(得分:0)

我在代码中添加了一个小改动 - 一旦我们得到左边的部分,就按字典顺序排序。这在 Java 中可能是必需的。 当我用java写上面的代码时,我得到了“asdadsa”而不是“adsasda”

Java 代码如下:

use Drupal\Component\Utility\Html;

可能需要进行一些重构,例如使用 Java 中的现有库在 StringBuilder 中添加重复字符。但是上面的代码提供了解决方案。