leetcode 132 分割回文串 II
给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。
返回符合要求的最少分割次数。
示例:
输入: "aab"
输出: 1
解释: 进行一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。
使用dfs完败,字符串中如果回文串少且长度够长,直接超时JJ。
1 public class _132 { 2 3 /** 4 * @param t 回文串的长度 5 * @param res 最少的分割次数 6 * @param depth 当前递归的层数 7 * @param cur 当前所在的字符位置 8 * @return 最小的分割次数 9 */ 10 public int dfs(int[][] t , int res, int depth, int cur) { 11 if (res < depth || cur == -1) return res; 12 13 for (int i = t[cur][0]; i > 0; --i){ 14 if (cur - t[cur][i] == -1) { 15 res = Math.min(res, depth); 16 } 17 res = Math.min(dfs(t, res, depth+1, cur-t[cur][i]), res); 18 } 19 return res; 20 } 21 22 public int minCut(String s) { 23 /// 查找s中最后一个字符的回文串,有几个不同的回文串就有几个分支 24 int len = s.length(); 25 int[][] t = new int[len][2*len]; // t[i][...];t[i]是一个一维数组,它存储以i结尾的回文串的长度, 其中t[i][0]存储回文串的个数 26 27 for (int i = 0; i < len; i++){ // 判定奇数的回文串 28 for (int j = 0; i - j >= 0 && i + j < len; j++){ // j表示偏移长度 29 // 判定的字符串的边界: i-j, i+j 30 if (s.charAt(i-j) == s.charAt(i+j)){ 31 int count = t[i+j][0]; 32 t[i+j][count+1] = (i+j) - (i-j) + 1; 33 34 System.out.println("测试---"+(i-j)+", "+(i+j)+", "+(i+j-(i-j)+1)); 35 36 ++t[i+j][0]; 37 } else { 38 break; 39 } 40 } 41 } 42 43 for (int i = 0; i < len-1; i++){ // 判定偶数的回文串 44 for (int j = 0; i-j >= 0 && i+j+1 < len; j++){ 45 // 边界为 i-j, i+1+j 46 if (s.charAt(i-j) == s.charAt(i+1+j)){ 47 int count = t[i+1+j][0]; 48 t[i+1+j][count+1] = (i+1+j+1) - (i-j); 49 50 System.out.println("测试---"+(i-j)+", "+(i+j+1)+", "+((i+1+j+1) - (i-j))); 51 52 ++t[i+1+j][0]; 53 } else { 54 break; 55 } 56 } 57 } 58 59 // for (int i = 0; i < len; ++i){ 60 // System.out.print("以"+i+"位置结束的回文串的长度:"); 61 // for (int j = 1; j <= t[i][0]; ++j){ 62 // System.out.print(t[i][j]+" "); 63 // } 64 // System.out.println(); 65 // } 66 System.out.println("================="); 67 return dfs(t, 65535, 1, len-1)-1; 68 } 69 70 public static void main(String[] args) { 71 int res = new _132().minCut("alksjdfhgeiige"); 72 System.out.println("answer: "+res); 73 } 74 }