Word Break
Given a string s and a dictionary of words dict, determine if s can be break into a space-separated sequence of one or more dictionary words.
Given s = "lintcode"
, dict = ["lint", "code"]
.
Return true because "lintcode" can be break as "lint code"
.
Tags Expand
原题地址:http://www.lintcode.com/en/problem/word-break/
这道题我从前一天的晚上一直纠结到第二天,然后在参考答案的帮助下终于解决了。
一开始最初的想法是用recursive去做,而且感觉这长的就像recursive,后来一提交发现超时。
然后想换成DP的方法试一试,初始化一个boolean数组dp dp[i]的值表示string s的子字符串(0,i)能否被dict中的字符所分割。
这样很容易得出DP方程:如果DP[ j ]为true, 那么存在i DP[ i ]为true 并且 dict包含substring(i,j) 即DP[ j ] = DP[ i ]+s.substring( i,j )。
然后很快写出了第一个版本的代码:
public class Solution {
/**
* @param s: A string s
* @param dict: A dictionary of words dict
*/
public boolean wordBreak(String s, Set<String> dict) {
// write your code here
boolean[] check = new boolean[s.length()+1];
check[0] = true;
if (s == null || s.length() == 0){
return true;
}
for (int i = 1; i<= s.length(); i++){
for (int j = i-1;j>=0;j--){
if(check[j]){
String a = s.substring(j,i-j);
if (dict.contains(a)){
check[i] = true;
break;
}
}
}
}
return check[s.length()];
}
}
但是后来发现总是卡在一个测试用例上 S="aaaaaaa" , dict=""aaaa","aaa""上 一开始怎么也想不明白,以为是自己的下标出了问题,后来扔到IDE里面debug了之后才发现真是狡猾。我的程序只要循环到第三个a的时候就会满足dict.contains 所以我的字符串被分割成了aaa aaa a 自然最后结果为false。
最初我想的解决方案是在内层循环里面添加判断条件,但是后来发现不能解决问题。只能含泪重写
第二版代码(AC)
public class Solution {
/**
* @param s: A string s
* @param dict: A dictionary of words dict
*/
public boolean wordBreak(String s, Set<String> dict) {
// write your code here
int max = 0;
for(String a:dict){
max = Math.max(max,a.length());
}
boolean[] dp = new boolean[s.length()+1];
dp[0] = true;
for(int i = 1;i<=s.length();i++){
for(int j = 1;j<=max&&j<=i;j++){
if(dp[i-j]){
String word = s.substring(i-j,i);
if(dict.contains(word)){
dp[i]=true;
break;
}
}
}
}
return dp[s.length()];
}
}
思路其实就是对于每一个i 从0 到 i 把dict里面的单词都遍历一遍看满足不满足contain (代码中的max表示dict中长度最长的那个单词)这样就可以避免上述测试用例带来的bug