I:
Given a string s, partition s such that every substring of the partition is a palindrome.
Return all possible palindrome partitioning of s.
For example, given s ="aab",
Return
[ ["aa","b"], ["a","a","b"] ] 先切割,而后判断是否为回文。若是,则将剩余部分继续进行深度遍历。
1 class Solution { 2 public: 3 vector<vector<string>> partition(string s) { 4 if(s.length()<1) return res; 5 dfs(s,0); 6 return res; 7 } 8 9 void dfs(string s,int n){ 10 int len=s.length(); 11 if(n==len){ 12 res.push_back(v); 13 return ; 14 } 15 for(int i=1;i<len-n+1;i++){ 16 string tmp=s.substr(n,i); 17 if(isPalindrome(tmp)){ 18 v.push_back(tmp); 19 dfs(s,n+i); 20 v.pop_back(); 21 } 22 } 23 } 24 25 bool isPalindrome(string s){ 26 int n=s.length(); 27 int i=0,j=n-1; 28 while(i<j){ 29 if(s[i]!=s[j]) 30 return false; 31 i++; 32 j--; 33 } 34 return true; 35 } 36 vector<string> v; 37 vector<vector<string>> res; 38 };
II:
Given a string s, partition s such that every substring of the partition is a palindrome.
Return the minimum cuts needed for a palindrome partitioning of s.
For example, given s = "aab"
,
Return 1
since the palindrome partitioning ["aa","b"]
could be produced using 1 cut.
从后往前构造二维数组isPalin,用于存储已经确定的回文子串。isPalin[i][j]==true代表s[i,...,j]是回文串。
在构造isPalin的同时使用动态规划计算从后往前的最小切分数,记录在min数组中。min[i]代表s[i,...,n-1]的最小切分数。
(上述两步分开做会使得代价翻倍,容易TLE)
关键步骤:
1、min[i]初始化为min[i+1]+1,即初始化s[i]与s[i+1]之间需要切一刀。这里考虑边界问题,因此min数组设为n+1长度。
2、从i到n-1中间如果存在位置j,同时满足:(1)s[i,...,j]为回文串;(2)1+min[j+1] < min[i]。
那么min[i]=1+min[j+1],也就是说一刀切在j的后面比切在i的后面要好。
1 class Solution { 2 public: 3 int minCut(string s) { 4 int n=s.length(); 5 if(n==1) return 0; 6 vector<vector<bool>> isPali(n,vector<bool>(n,false)); 7 vector<int> min(n+1,-1); 8 for(int i=0;i<n;i++){ 9 isPali[i][i]=true; 10 } 11 for(int i=n-1;i>=0;i--){ 12 min[i]=min[i+1]+1; 13 for(int j=i+1;j<n;j++){ 14 if(s[i]==s[j]){ 15 if(j==i+1||isPali[i+1][j-1]==true){ 16 isPali[i][j]=true; 17 if(j==n-1) 18 min[i]=0; 19 else if(min[i]>min[j+1]+1) 20 min[i]=min[j+1]+1; 21 } 22 } 23 } 24 } 25 return min[0]; 26 } 27 };