131. Palindrome Partitioning
仅供自己学习
思路:
直接深搜即可,我们用out暂存一个回文子串,res为所有可能的回文子串存放的数组,是最终结果,用start作为深搜的起点位置,我们需要一个函数来判断是否为回文串,一个DFS函数,即可。
例如s为aabc的时候,a -> a -> b -> c -> bc -> ab -> abc -> aa -> b -> c -> bc -> aab -> aabc,一开始会把所有元素组成单个的回文串,每个都添加进out,当搜索长度等于s的长度后就加入res最终的数组,当发现aa这个回文字串后,就会把“aa”添加进out数组里暂存,然后又从b开始往下,寻找,因为没能找到回文串那么就是“aa”,“b”,“c”作为一个回文子串结果。
1 class Solution { 2 private: 3 vector<vector<string>> res; 4 vector<string> out; 5 public: 6 vector<vector<string>> partition(string s) { 7 DFS(s,out,res,0); 8 return res; 9 } 10 11 void DFS(string s,vector<string>& out,vector<vector<string>>& res,int start){ 12 if(start==s.size()) {res.push_back(out);return;} 13 for(int i=start;i<s.size(); ++i){ 14 if(!ispalindrome(s,start,i)) continue; 15 out.push_back(s.substr(start,i-start+1)); //s.substr函数是复制一份从start到i-start+1这个范围的元素加入进out里面 16 DFS(s,out,res,i+1); 17 out.pop_back(); 18 } 19 } 20 21 bool ispalindrome(string s,int start,int end){ 22 while(start<end){ 23 if(s[start]!=s[end]) return false; 24 start++;end--; 25 } 26 return true; 27 } 28 };
我们也可以用表来记录,然后每次查表是否为回文子串即可。dp[j][i]是 [j,i]区间的子串。
1 class Solution { 2 private: 3 vector<vector<string>> res; 4 vector<string> out; 5 public: 6 vector<vector<string>> partition(string s) { 7 vector<vector<bool>> dp(s.size(),vector<bool>(s.size())); 8 for(int i=0;i<s.size();++i){ 9 for(int j=0;j<=i;++j){ //这里是竖着初始化。 10 if(s[i]==s[j]&&(i-j<=2||dp[j+1][i-1])){ //每次判断第一个和最后一个等不等,并且当字串长度小于等于2的时候,如果第一个和最后一个相等就是回文串。长度大于2时,就判断他里面的两个是不是回文串 11 dp[j][i]=true; 12 } 13 } 14 } 15 DFS(s,out,res,0,dp); 16 return res; 17 } 18 19 void DFS(string s,vector<string>& out,vector<vector<string>>& res,int start,vector<vector<bool>>& dp){ 20 if(start==s.size()) {res.push_back(out);return;} 21 for(int i=start;i<s.size(); ++i){ 22 if(!dp[start][i]) continue; 23 out.push_back(s.substr(start,i-start+1)); 24 DFS(s,out,res,i+1,dp); 25 out.pop_back(); 26 } 27 } 28 };