为给定字符串生成所有可能的回文

Generating all possible palindromes for a given string

本文关键字:有可能 回文 字符串      更新时间:2023-10-16
Inputs : I.1) A string of characters
Outputs: O.1) Total number of palindromes found
         O.2) Palindromes output on standard output
Note : duplicate palindromes are not allowed
             output need not be sorted
single characters are a palindrome.

我已经通过回溯解决了上述问题,但它为一个大的输入字符串提供了 TLE。因此,如果解决方案避免递归,这将是有益的。TLE 的输入是 :- amitabhbacchan
这是我的实现:

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int isSafe(int *a, int i) {
    if (a[i] == 0) {
        return 1;
    }
    else {
        return 0;
    }
}
int isPalin(string b) {
    if (b.length() == 0) {
        return 0;
    }
    if (b.length() == 1) {
        return 1;
    }
    string c = b;
    std::reverse(c.begin(), c.end());
    if (c == b) {
        return 1;
    }
    else {
        return 0;
    }
}
void palindrome(string a, string b, int *vec, std::set<string>&res) {
    if (isPalin(b)) {
        if (res.find(b) != res.end()) {
            return;
        }
        res.insert(b);
    }
    for (int i = 0; i < a.length(); i++) {
        if (isSafe(vec, i)) {
            b.push_back(a[i]);
            vec[i] = 1;
            palindrome(a, b, vec, res);
            b.pop_back();
            vec[i] = 0;
        }
    }
}
int main(void) {
    string a = "ababcdef";
    string c = "";
    int *vec;
    std::set<string>res;
    vec = (int*)malloc(a.length()*sizeof(int));
    for (int i = 0; i < a.length(); i++) {
        vec[i] = 0;
    }
    palindrome(a, c, vec, res);
    std::set<string>::iterator it;
    for (it = res.begin(); it != res.end(); it++) {
        cout << *it << endl;
    }
    return 0;
}

这里的基本问题是你生成回文的效率非常低。特别是,您正在尝试生成输入的每个可能的排列,然后检查每个输入是否是回文。

取而代之的是,考虑字符串是回文的基本要求(中间之前的所有字符都与中间之后的字符相同,并且顺序相反)。因此,除了奇数长度回文的中间字符外,回文中的所有其他字符都必须出现偶数次。

我首先将字符分为两组:偶数出现和奇数出现。偶数次出现的字符,您只插入工作集中的一半字符。也就是说,给定(例如)输入中的aabbccde,您将它分成两部分,一部分包含abc,另一部分包含de

然后你可以通过生成abc(和abacbc)的所有排列来生成回文,这些排列按正向顺序输出,然后以相反的顺序输出相同的集合(例如,abc后跟cba给出abccba)。然后对于其中的每一个,您可以在中间插入另一个集合中的一个字符,这样您就可以得到abcdcbaabcecba )。然后重新排列这些输入以获得(例如)acb并重复该过程以获得acbbcaacbdbcaacbebca

生成"偶数"输入的所有排列的一种方法是使用 std::next_permutation .

请注意,这样您就不会花时间生成许多不是回文的可能排列。你事先知道,你产生的每一个结果都将是一个回文。