回文字符串切割问题

3 篇文章 0 订阅

问题描述

  • 对任意一个字符串进行切割,使得切割后的每一个字符串都是回文字符串。列出切割后的所有结果。

方法一:深度优先搜索

  • 以string s的下标调用dfs函数,index表示当前要开始切割的下标,i表示目前要切割的终点位置,其中index<=i
//判断是否是回文
bool isPalindrome(string &s)
{
    for(int i=0;i<s.length()/2;i++)
    {
        if(s[i]!=s[s.length()-i-1])
            return false;
    }
    return true;
}

//字符串切割
//ans存放切割的所有结果
//cur存放当前的切割结果
void dfs(string &s,vector<vector<string>>&ans,vector<string> &cur,int index)
{
    if(index==s.length())
        ans.push_back(cur);
    else
    {
        for(int i=index;i<s.length();i++)
        {
            if(isPalindrome(s.substr(index,i-index+1)))
            {
                cur.push_back(s.substr(index,i-index+1));
                dfs(s,ans,cur,i+1);
                cur.pop_back();
            }
        }
    }
}
  • 问题
    • 上述代码很有可能会超时,因为每一个子串都要重新判断是否为回文串。
  • 改进
    • 声明一个变量表示从下标i开始j结束的字符串是否是回文vector<vector<bool>>isPalind(s.length(),vector<bool>(s.length(),false));
    • 如果长度为len-2,下标开始地址为i+1的子串是回文串,并且s[i]==s[i+len-1],则说明长度为len,下标开始地址为i的子串也是回文串。即满足递归式isPalind[i][i+len-1]=isPalind[i+1][i+len-2]&&(s[i]==s[i+len-1])
    • 改进后的代码如下:
void isPalindrome(vector<vector<bool>>&isPalind,string &s)
{
    for(int i=0;i<s.length();i++)
        isPalind[i][i]=true;
    for(int i=1;i<s.length();i++)
        isPalind[i][i-1]=true;
    for(int len=2;len<=s.length();len++)
    {
        for(int i=0;i+len<=s.length();i++)
        {
            isPalind[i][i+len-1]=isPalind[i+1][i+len-2]&&(s[i]==s[i+len-1]);
        }
    }
}

void dfs(string &s,vector<vector<string>>&ans,vector<string> &cur,int index,vector<vector<bool>>&isPalind)
{
    if(index==s.length())
        ans.push_back(cur);
    else
    {
        for(int i=index;i<s.length();i++)
        {
            if(isPalind[index][i])
            {
                cur.push_back(s.substr(index,i-index+1));
                dfs(s,ans,cur,i+1,isPalind);
                cur.pop_back();
            }
        }
    }
}

在调用dfs函数之前,一定要先调用isPalindrome函数,生成isPalind数组。这样避免重复求一个字符是否是回文串,节省了很多时间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值