一、题目
1、审题
2、分析
给出一个字符串 S,一个字典表 dict,判断 S 是否能由 dict 中的字符串所组成,其中 dict 中的字符串能够多次使用。
二、解答
1、思路:
方法一、
使用一个 DP 数组记录 S 从下标 0 到当前下标位置是否能够正确匹配。
①、从下标 i = 1 开始遍历,在字典序列 dict 中查找是否能够正确匹配到S 的下标 i ;
public boolean wordBreak(String s, List<String> wordDict) { int len = s.length(); boolean[] f = new boolean[len+1]; f[0] = true; // f[i] = true: 0 ~ i-1 是能匹配的。 for(int i = 1; i <= len; i++) { for(String str: wordDict) { if(i - str.length() >= 0 && f[i - str.length()]) { if(s.substring(i - str.length(), i).equals(str)) { f[i] = true; break; } } } }
方法二、
使用一个 DP 数组记录 S 从下标 0 到当前下标位置是否能够正确匹配。
public boolean wordBreak11(String s, List<String> wordDict) { int len = s.length(); boolean[] f = new boolean[len+1]; f[0] = true; // f[i] = true: 0 ~ i-1 是能匹配的。 for(int i = 1; i <= len; i++) { for (int j = 0; j < i; j++) { if(f[j] && wordDict.contains(s.substring(j, i))) { f[i] = true; break; } } } return f[len]; }
方法三、
采用 BFS + DP 。
①、采用一个 DP 数组记录到当前位置是否能够正确匹配。
采用一个Queue 记录当前的广度遍历的节点。
采用一个 Set 存储字典的所有字符串,方便比较是否包含 S 的子串。
②、可以将查找过程看做一张图,每次从一个节点开始 BFS 查找所有的节点,并填充 DP数组为 true,同时将节点加入 Queue中,继续进行 BFS 遍历。
public boolean wordBreak12(String s, List<String> wordDict) { int max_len = -1; for(String word: wordDict) max_len = Math.max(max_len, word.length()); Set<String> wordDictSet = new HashSet<>(wordDict); Queue<Integer> queue = new LinkedList<Integer>(); boolean[] visited = new boolean[s.length()]; queue.add(0); while(!queue.isEmpty()) { int start = queue.remove(); for(int end = start + 1; end <= s.length() && end - start <= max_len; end++) { if(wordDictSet.contains(s.substring(start, end)) && !(end < s.length() && visited[end])) { if(end == s.length() ) { return true; } queue.add(end); visited[end] = true; } } } return false; }