问题描述
- 对任意一个字符串进行切割,使得切割后的每一个字符串都是回文字符串。列出切割后的所有结果。
方法一:深度优先搜索
- 以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])
- 改进后的代码如下:
- 声明一个变量表示从下标i开始j结束的字符串是否是回文
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数组。这样避免重复求一个字符是否是回文串,节省了很多时间。