这一题是在上一题Word Break的基础上求总共有多少种分割方法,一定程度上可以被抽象成组合问题,而往往组合问题采用递归算法可以实现,所以想到递归也就是很自然的事。
下面是AC代码。
1 /** 2 * Given a string s and a dictionary of words dict, add spaces in s to construct a sentence 3 * where each word is a valid dictionary word. Return all such possible sentences. 4 * 这道题是一个递归问题,如果对第一道word break的DP的递推式理解的话,就不难解这一题 5 * 采用递归的方法把一个规模较大的问题递归成一个规模较小的问题 6 * @param s 7 * @param dict 8 * @return 9 */ 10 public ArrayList<String> wordBreak2(String s,Set<String> dict){ 11 //先采用dp获得标识信息的数组 12 boolean[] Db = wordB(s,dict); 13 //if it is not a breakable string, return empty 14 if(Db == null || Db[s.length()-1] == false) 15 return new ArrayList<String>(); 16 ArrayList<String> list = new ArrayList<String>(); 17 //采用递归的方法求解中共有多少种字符串分割方法 18 subProblem(list,new String(), Db, s.length()-1,dict, s); 19 20 return list; 21 } 22 /** 23 * 24 * @param list 相当于全局的一个变量 25 * @param curr 从最后到目前为止,已经形成的字符串,在这次迭代中把当前的一个合法单词放到curr前面,并且以“ ”分割 26 * @param Db 标识信息,一直都需要 27 * @param end 表示目前问题的规模 28 * @param dict 29 * @param s 30 */ 31 private void subProblem(ArrayList<String> list, String curr, boolean[] Db, int end,Set<String> dict,String s) 32 { 33 //迭代结束的基本情况,当所有串都已经获得时,就把这种分割方式的结果放到全局的list中 34 if(end == -1) 35 list.add(curr.substring(0,curr.length())); 36 37 int j = end-1; 38 while(j>=0){ 39 if(Db[j] && dict.contains(s.substring(j+1,end+1)) ) 40 { 41 String cur = s.substring(j+1,end+1) + " "+curr; 42 subProblem(list, cur, Db, j, dict, s); 43 } 44 j--; 45 } 46 //这是特殊情况 47 if(dict.contains(s.substring(0,end+1))) 48 { 49 String cur = s.substring(0,end+1) + " "+curr; 50 subProblem(list, cur, Db, -1, dict, s); 51 } 52 } 53 /** 54 * DP过程 55 * @param s 56 * @param dict 57 * @return 58 */ 59 private boolean[] wordB(String s, Set<String> dict){ 60 // if the dict is empty, return false 61 if (dict.size() <= 0) 62 return null; 63 boolean[] Db = new boolean[s.length()]; 64 // initialize 65 if (dict.contains(s.substring(0, 1))) 66 Db[0] = true; 67 else 68 Db[0] = false; 69 // DP process 70 for (int i = 1; i < s.length(); i++) { 71 Db[i] = false; 72 int j = i - 1; 73 while (j >= 0) { 74 if (Db[j] && dict.contains(s.substring(j + 1, i + 1))) { 75 Db[i] = true; 76 break; 77 } 78 j--; 79 } 80 if (!Db[i] && j < 0 && dict.contains(s.substring(0, i + 1))) 81 Db[i] = true; 82 83 } 84 return Db; 85 }