关于字符回文串问题,帮修改一下

给定一个字符串 S,定义操作为:将其中 [l_i,r_i] 字符都在 ASCII 数值意义下 +1,特别的,字母 z+1 变成 a

问:你可以任意多次顺序执行k次操作,能否把S变为一个回文串?

输入格式

第一行一个字符串 S。

接下来一行一个正整数 k,含义如题。

接下来 k 行,每行两个整数 [l,r] 表示操作的范围。

输出格式

YESNO

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>

using namespace std;

bool canMakePalindrome(string s, int k) {
    unordered_map<char, int> freq;
    for (char c : s) {
        freq[c]++;
    }

    vector<pair<char, int>> workList;
    for (auto f : freq) {
        char c = f.first;
        int count = f.second;

        if (count % 2 != 0) {
            workList.push_back({c, count});
        }
    }

    while (!workList.empty() && k > 0) {
        char c = workList.back().first;
        int count = workList.back().second;
        workList.pop_back();

        if (count % 2 != 0) {
            if (k >= count / 2) {
                k -= count / 2;
                workList.push_back({c, count - count / 2});
            } else {
                return false;
            }
        }
    }

    return true;
}

int main() {
    int k;
    cin >> k;

    string s;
    int l, r;

    for (int i = 0; i < k; i++) {
        cin >> l >> r;
        s.erase(l - 1, r - l + 2);
        s.insert(l - 1, r - l + 2, 'a');
    }

    if (canMakePalindrome(s, k)) {
        cout << "Yes" << endl;
    } else {
        cout << "No" << endl;
    }

    return 0;
}

用字符串好像更简单,写一个专门判断是否为回文数的函数,然后每转换一次,调用一下回文函数

img


试试效果

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
 
using namespace std;
 
bool canMakePalindrome(string s, int k) {
    unordered_map<char, int> freq;
    for (char c : s) {
        freq[c]++;
    }
 
    vector<pair<char, int>> workList;
    for (auto f : freq) {
        char c = f.first;
        int count = f.second;
 
        if (count % 2 != 0) {
            workList.push_back({c, count});
        }
    }
 
    while (!workList.empty() && k > 0) {
        char c = workList.back().first;
        int count = workList.back().second;
        workList.pop_back();
 
        if (count % 2 != 0) {
            if (k >= count / 2) {
                k -= count / 2;
                workList.push_back({c, count - count / 2});
            } else {
                return false;
            }
        }
    }
 
    return true;
}
 
int main() {
    int k;
    cin >> k;
 
    string s;
    int l, r;
 
    for (int i = 0; i < k; i++) {
        cin >> l >> r;
        s.erase(l - 1, r - l + 2);
        s.insert(l - 1, r - l + 2, 'a');
    }
 
    if (canMakePalindrome(s, k)) {
        cout << "Yes" << endl;
    } else {
        cout << "No" << endl;
    }
 
    return 0;
}


不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这篇博客: 排序算法—快排中的 2、之后循环这两步,直到L与R相等,我们将基准数放在他们为下标的位置 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:

    即如下图所示:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R7GLnsSB-1617951441568)(C:\Users\11874\AppData\Roaming\Typora\typora-user-images\image-20210306180733196.png)]

    这样,我们就将小于基准数的数字全部放在了基准数的左边,大于基准数的全部放在了基准数的右边。

    我们将基准数的左边的数字和基准数右边的数字分别进行上述所有步骤如下图,直至一个分支只有一个元素。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5ncEWoWz-1617951441569)(C:\Users\11874\AppData\Roaming\Typora\typora-user-images\image-20210306180756618.png)]


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^