回文字符串及其变种
回文partition一般有以下几种情况:
1. 求所有的partition结果。这个一般用DFS来解。
2. 最后结果是一个整数,比如Palindrome Partitioning II。这个用DP来解
3. 最后求一个结果,比如最小切法。这个用DP+backtrack来解
4. 最长回文子串
问题1:求所有的回文partition结果,用简单的DFS就可以求出。
bool isPalin(string &s,int l,int r) { while(l<r) { if(s[l]!=s[r]) return false; l++; r--; } return true; } vector<vector<string>> partition(string s) { // Start typing your C/C++ solution below // DO NOT write int main() function //DFS vector<vector<string>> res; if(s.empty()) return res; vector<string> path; dfs(s,0,path,res); return res; } void dfs(string& s,int curpos,vector<string>& path,vector<vector<string>>& res) { if(curpos==s.size()) { res.push_back(path); return; } for(int i=curpos;i<s.size();i++) { if(isPalin(s,curpos,i)) { path.push_back(s.substr(curpos,i-curpos+1)); dfs(s,i+1,path,res); path.pop_back(); } } }
---改进版,用一个二维数组预处理子串是否回文,避免上面解法重复计算子串回文。
vector<vector<string>> partition(string s) { // Start typing your C/C++ solution below // DO NOT write int main() function vector<vector<string>> res; if(s.empty()) return res; int n = s.size(); vector<vector<bool>> palin; for(int i=0;i<n;i++) palin.push_back(vector<bool>(n)); for(int i=0;i<n;i++) palin[i][i] = true; for(int i=n-2;i>=0;i--) //注意:这里从i大的开始,从0开始时错误的,因为例如计算palin[0][5]需要palin[1][4],而palin[1][4]此时是未初始化的。 { if(s[i]==s[i+1]) palin[i][i+1] = true; else palin[i][i+1] = false; for(int j=i+2;j<n;j++) { if(palin[i+1][j-1]&&s[i]==s[j]) palin[i][j] = true; else palin[i][j] = false; } } vector<string> path; dfs(0,s,path,palin,res); return res; } void dfs(int pos,string& s,vector<string>& path,vector<vector<bool>>& palin,vector<vector<string>>& res) { if(pos==s.size()) { res.push_back(path); return; } for(int i=pos;i<s.size();i++) { if(palin[pos][i]) { path.push_back(s.substr(pos,i-pos+1)); dfs(i+1,s,path,palin,res); path.pop_back(); } } }
问题2:求回文最小partition个数。---DP求解