找到字符串中的所有回文

find all palindromes inside a string

本文关键字:回文 字符串      更新时间:2023-10-16

我被卡住了,似乎不知道该何去何从。如果有任何关于我应该如何处理这个问题的提示或建议,我将不胜感激。我已经想了9个多小时了,运气不好。

问题如下:

如果字符串s的前后读法相同,则称其为回文。s的分解是s的一组不重叠的子串,其级联为s。

编写一个C++程序,将一个字符串作为输入,并计算它的所有palin-dromic分解。例如,如果s是字符串02044551881,则分解020,44 5 1881是一个回文分解。也是

0 2 0 4 4 5 1 8 8 1

0 2 0 4 4 5 1 88 1

0 2 0 4 5 1881

0 2 0 44 5 1 8 8 1

0 2 0 44 5 1 88 1

020 4 4 5 1 8 8 1

020 4 4 5 1 88 1

020 4 4 5 1881

020 44 5 1 8 8 1

020 44 5 1 88 1

020 44 5 1881

这是一个班级项目。

到目前为止我有:

#include <iostream>
#include <string>
using namespace std;
void palDecom(string str1);
bool isPal(const string &str);
void subPal(string str1);
int main()
{
    string s = "0204451881";
    palDecom(s);
    subPal(s);
    return 0;
}
//shows the decomposition as the single  char of the string
//takes a string as input
void palDecom(string str1)
{
    int stringLastIndex = (str1.length());
    for (int i = 0; i < stringLastIndex; i++)
    {
        cout<< str1[i] <<" ";
    }
    cout<<endl;

}
void subPal(string str1)
{
    int stringLastIndex = (str1.length());

    for (int curIndx = 0; curIndx < stringLastIndex; curIndx++)
    {
            for(int comparIndx = 1; comparIndx < stringLastIndex; comparIndx++)
            {
                //cout<< "i was in this loop"<<endl;
                if (isPalindrome((str1,curIndx,comparIndx)))

                        //cout<<str1.substr(0,curIndx-1)<<" "<<  str1.substr(curIndx,comparIndx) <<" "<< str1.substr(comparIndx,stringLastIndex)<<endl;

            }
    }

}
bool isPal(const string &str)
{
    int start=0, end=str.length()-1;
    while (start < end) {
        if (str[start++] != str[end--])
            return false;
    }
    return true;
}

实际上,我刚刚实现了这一点:

回文分解为组合拆分

这意味着每个回文都将"分割";基于多少";层";它拥有的回文

例如:序列

  • 12213443
  • ->1221+3443
  • ->1+22+1+3+44+3
  • ->1+2+2+1+3+44+3

当你向下解析字符串时,可能性只会增加一个较大的回文可以分解的数量,直到你有1个字符宽的回文。

诚然,我意识到回文可以重叠:

  • 1221221
  • ->1221+22+1
  • OR->1+22+1221

这是一个额外的难题,但肯定是可以解决的。

此外,你可以选择将较小的回文组合在一起创建较大的回文

就我个人而言,我认为这条思路将带来一个更好的算法和方法来解决上述问题,因为在一个方向上迭代的同时编写新的回文可能比在一个方面分解它们更容易。

我认为最好的方法是开始玩回文,并绘制出可能的分解图通过分析,您应该能够找到一个重复的模式,然后可以将其映射到递归解决方案。

无论如何,这个答案肯定可以使用递归。这里有一个明确的模式;你只需要更多地探索并找到它

我希望我能有一个更明确的答案,但我自己也在努力解决这个问题。我希望其他人可以编辑这个并拿起线程?

使用递归通过从左到右扫描字符串来解决此问题。

保留一堆先前的回文分区,这些分区已经在整个字符串中的"当前位置"的"左侧"找到。这个堆栈可以是一个数组或std::向量,指针指向之前找到的每个回文的末尾(即最后一个字符后的一个)。在这种情况下,"当前位置"由堆栈的顶部元素表示,如果堆栈为空,则由字符串的开头表示。

递归的基本/退出情况是当前位置指的是整个字符串的末尾。在这种情况下,你已经用尽了绳子。打印出回文堆栈指示的回文(从底部开始),然后返回。(提示:不要更改原始字符串以插入nul终止符来将每个回文打印为字符串。相反,只需根据堆栈上的分区逐字符打印每个回文,在回文之间打印空格,并在堆栈末尾打印换行符。)

否则,有一个循环,从1一直到从当前位置开始的字符串中剩余的字符数。在每次迭代中,测试当前位置是否是长度等于循环索引的回文。如果它是这样一个回文,那么将该回文的分区推到堆栈上,并向下递归到更深的一级。

这样就可以了。

我不会使用std::堆栈来实现堆栈。请使用std::矢量或数组。如果使用std::vector,那么在递归中不要对其进行结构操作(例如-push_back、pop_back等)。相反,在开始递归之前,只需调整()大小以容纳strlen(str)分区元素,因为当字符串的每个字符都是回文时,堆栈最深。然后在递归中,只需传递堆栈的逻辑当前大小。这告诉您下一个回文分区应该放在哪里的索引(即-在索引大小),并允许您访问堆栈中任何以前存在的顶部元素(即-索引大小-1)。这种方法适用于数组或std::向量。

如果您确实想使用std::vector::push_back()(或std::stack),那么您只需要在每次递归返回后记住std::vector::pop_back(。这种方法将允许您不需要显式地传递堆栈的"逻辑"大小,因为向量本身会知道其正确的大小。

#include <iostream>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <iomanip>
using std:: cin; 
using std:: cout;
using std:: endl;
using std:: setw;
const int MAX_LEN = 100;
int palDecom(const char str[]);
bool isPal(const char str[], int start, int end);
int main()
{
    char str[MAX_LEN];
    cin >> setw(MAX_LEN) >> str;
    cout << palDecom(str) ;
    return EXIT_SUCCESS;
}

int palDecom(const char str[])
{
    int counter=0;
    for (int i = 1; i < strlen(str) ; i++)
        for(int lastindex = strlen(str)-1; lastindex < strlen(str) ; lastindex--)
        {
            if(isPal(str, i , lastindex-1))
                counter ++;
        }
    return counter;
}

bool isPal(const char str[], int start, int end)
{
    if(start == strlen(str))
        return 1;
    if (str[start] == str[end]){
        isPal(str, str[start], str[end-1]);
        return true;
    }
    return false;
}