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".

/* 
* “leetleet” ["leet", "code"] return true
*/
public class Solution {
    public boolean wordBreak(String s, Set<String> dict) {
        if(s == null||dict.isEmpty())
            return false;
        int length = s.length();
        boolean[][] seg = new boolean[length][length + 1];
        for(int len = 1; len <= length; len++){
            for(int i = 0; i < length; i++){
                int tmp = i + len;
                if(i+len > length)
                        tmp = length;
                String t = s.substring(i, tmp);
                if(dict.contains(t)){
                    seg[i][len] = true;
                    continue;
                }
                for(int k = 1; k < len; k++){
                    if(seg[i][k] && seg[i+k][len-k]){
                        seg[i][len] = true;
                        break;
                    }
                }
            }
        }
        return seg[0][length];
        
    }
}

 ref: http://www.cnblogs.com/feiling/p/3357022.html


public
class Solution { public boolean wordBreak(String s, Set<String> dict) { boolean[] dp = new boolean[s.length()+1]; dp[0] = true; int len = s.length(); for(int i = 0; i< len; i++){ if(!dp[i]) continue; for(String e : dict){ // end 为 dict 中的单词长度在substring终止时的下标 int end = i+e.length(); if(end > s.length()) continue; String sub = s.substring(i, end); if(dict.contains(sub)) dp[end] = true; } } return dp[len]; } }

Ref : 水中的鱼 + word break

[Thoughts]

一个DP问题。定义possible[i] 为S字符串上[0,i]的子串是否可以被segmented by dictionary.

那么

possible[i] = true      if  S[0,i]在dictionary里面

                = true      if   possible[k] == true 并且 S[k+1,j]在dictionary里面, 0<k<i

               = false      if    no such k exist.

[Code]

实现时前面加一个dummy节点,这样可以把三种情况统一到一个表达式里面。

我不确定对: 没有额外空间,空间O(1)。每次recursion,都要loop O(n), 时间O(n^n)

毫无意外是会超时的,要加速基本要上DP了。关键是DP记录什么东西不好想,反正我是想了很久都没想到。最后看了大牛的答案才明白。还是bottom up approach。比如String长度为0,问题成立吗? 然后String长度为1,成立吗? 一直到n。所以dp就是记录从头开始的substring的长度和问题能否成立的关系。关键是dp[i]怎样可以利用dp[k], k=0,.., i-1的结果?就要在找0到i-1中找到一个k,使得dp[k] && dict.contains(s.substring(k, i))为真。意义是从0到k-1之间的substring,已经有办法用字典的词组成了,而且如果k到i-1之间的substring也在字典里,那么从0开始,长度为i的string就可以由字典里的词组成。

注意的是dp[0] == true是因为如果整个词都在字典里,那么就可以由字典的词组成。

优化解法:一维DP

public class Solution {
    public boolean wordBreak(String s, Set<String> dict) {
        int n = s.length();
        boolean[] dp = new boolean[n+1];
        dp[0] = true;
        for (int i=1; i<=n; i++) {
            for (int j=0; j<i; j++) {
                if (dp[j] && dict.contains(s.substring(j,i))) {
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[n];
    }
}

空间 O(n), 时间O(n^2)

原文地址:https://www.cnblogs.com/RazerLu/p/3555173.html