Word Break:
Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.
For example, given
s = "leetcode"
,
dict = ["leet", "code"]
.
Return true because "leetcode"
can be segmented as "leet code"
.
将字典里的每个单词取出与字符串进行匹配,成功则截取此部分,进入迭代
- public class Solution
- {
- public boolean wordBreak(String s, Set<String> dict)
- {
- if (s == null || dict == null || dict.isEmpty() || s.equals(""))
- return false;
- return find(s, dict);
- }
- public boolean find(String s, Set<String> dict)
- {
- if (s.equals(""))
- return true;
- boolean flag = false;
- for (String str : dict) {
- if (s.startsWith(str)) {
- String ss;
- ss = s.substring(str.length(), s.length());
- flag = find(ss, dict);
- }
- if (flag)
- return true;
- }
- return false;
- }
超时
解法2:
保存一个迭代字典hash,里面是已经验证的可以构成s前缀的字符串。每次迭代将hash中的字符串与dict两两组合并判断是否是s的前缀,是的话加入新的hash。长度超过s则直接跳过。
false条件:hash为空,即上一轮的hash和dict没有构成新的字符串。
- public boolean wordBreak(String s, Set<String> dict)
- {
- if (s == null || dict == null || dict.isEmpty())
- return false;
- if (s.equals(""))
- return true;
- HashSet<String> hs = new HashSet<String>();
- for (String str : dict) {
- if(s.equals(str))
- return true;
- if (s.startsWith(str))
- hs.add(str);
- }
- return find(s, hs, dict);
- }
- public boolean find(String s, Set<String> check, Set<String> dict)
- {
- HashSet<String> hash = new HashSet<String>();
- for (String ss : check)
- for (String str : dict) {
- if (ss.length() + str.length() > s.length())
- continue;
- String newStr = ss + str;
- if (newStr.equals(s))
- return true;
- if (s.startsWith(newStr))
- hash.add(newStr);
- }
- if (hash.isEmpty())
- return false;
- return find(s, hash, dict);
- }
解法3:
创建boolean数组dp[],dp[i]==true则表明字符串s中的第i位可以达到
最优子结构:如果第i-1位可以构成,只用判断后面是否可以构成s。
出口条件:当dp[s.length-1]==true时,说明可以构成
public boolean wordBreak(String s, Set<String> dict)
{
boolean[] dp = new boolean[s.length()];
for (int i = 0; i < s.length(); i++) {
if (i > 0 && !dp[i - 1])
continue;
for (String str : dict) {
if (i + str.length() > s.length())
continue;
if (str.equals(s.substring(i, i + str.length()))) {
dp[i + str.length() - 1] = true;
}
if (dp[s.length() - 1]) {
return true;
}
}
}
return false;
}
Word Break II
Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word is a valid dictionary word.
Return all such possible sentences.
For example, given
s = "catsanddog"
,
dict = ["cat", "cats", "and", "sand", "dog"]
.
A solution is ["cats and dog", "cat sand dog"]
.
public List<String> wordBreak(String s, Set<String> dict)
{
boolean[] dp = new boolean[s.length()];
ArrayList<Integer>[] a =(ArrayList<Integer>[]) new ArrayList[s.length()];
for (int i = 0; i < s.length(); i++)
a[i] = new ArrayList<Integer>();
ArrayList<String> arr = new ArrayList<String>();
dp[0] = true;
for (int i = 0; i < s.length(); i++) {
if (i > 0 && !dp[i - 1])
continue;
for (String str : dict) {
if (i + str.length() > s.length())
continue;
if (s.substring(i, i + str.length()).equals(str)) {
dp[i + str.length() - 1] = true;
a[i].add(i + str.length());
}
}
}
foo(a, 0,new StringBuffer(""), s, arr);
return arr;
}
public void foo(ArrayList<Integer>[] a, int i, StringBuffer ss, String s,
ArrayList<String> arr)
{
for (Integer k : a[i]) {
if(i==0)
ss=new StringBuffer("");
ss.append(s.substring(i, k) + " ");
if (k==s.length())
arr.add(ss.substring(0, ss.length() - 1));
else
foo(a, k, ss, s, arr);
}
}
DP记录分割点对每个分割点i建立链表,保存所有可以达到的位置。最后dfs构建字符串。
注意每次i=0时,字符串要清空