139.Word Break (M)

1.Description(Medium)

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.

Example

Given s ="lintcode", dict =["lint", "code"].

Return true because"lintcode"can be break as"lint code".

2.Code

Solution 1:DFS

看到这题第一反应是DFS枚举查找,直到“探”到string尾部则算成功。但题目并不要求给出是如何break的,而只要判断是否能break。对这类判断“是”与“否”的可以用DFS暴力解决的题.

对于这道题,我们首先考虑暴力的方法。本题相当于用多个字符串组成该字符串,那么我们就枚举所有可能的放入字符串的方法,通过深度优先搜索,尝试所有可能。 对于一个字符串,考虑字典中的每个前缀是否是这个字典中的单词。若不是,则跳过该单词。若是则将该前缀从字符串中删除后,判断剩下的字符串能否由字典里的单词组成。 由于题目的数据加强,此题已经无法使用常规的DFS方式通过,我们更推荐更优秀的DP来实现。

代码思路

使用深度优先搜索,记录字符串,字典,以及当前需要判断的字符串的起始点 从当前字符串的起始点开始判断

代码框架

定义dfs
    递归的出口
    如果起始点已经在字符串的尾部
        停止,返回可以组成该字符串
    如果还未到结尾,枚举下一个字符串的长度。
        对于每种可能,判断该字符串是否在字典中
        如果在字典中:
            取出该字符串,判断剩下的是否可以
    找完所有可能后,仍然不行,直接返回这段字符串无法找到答案
    
    

时间复杂度:O(2^n),考虑当s = "aaaaaaaaaaab", dict = {"a", "aa", "aaa", ...., "aaaaaaaaa"} 空间复杂度:O(N),递归深度最深为N层

相关问题:

LintCode 582. Word Break II LintCode 683. Word break III LintCode 123. Word Search

public class Solution {
    public boolean wordBreak(String s, Set<String> dict) {
        return dfs(s, dict, 0); 
    }
    
    /**
     * 递归的定义
     * 判断字符串s[start: ]能否通过wordDict中的单词组成
    **/
    public boolean dfs(String s, Set<String> dict, int now) {
        // 递归的出口
        if (now == s.length()) {
            return true;
        }
        
        // 递归的拆解,枚举下一个字符串的长度len
        for (int len = 1; now + len <= s.length(); len++) {
            // 判断s[now: now + len]是否满足条件
            if (dict.contains(s.substring(now, now + len)) && dfs(s, dict, now + len)) {
                return true;
            }
        }
        return false;
    }
}

Solution 2: Dynamic Programming

state: f[i] 表示前i个字符能不能被完美切分。

function:f[i] = OR{f[j]}+ j+1~i is a word (优化:j只需要到最长的单词长度即可)

例: j=0,1,3,5 f[i] =f[0] || f[1] || f[3] || f[5]

Initialize: f[0]=true

answer:f[n]

 public boolean wordBreak(String s, Set<String> dict) {

         if (s == null || s.length() == 0) {
             return true;
         }

        int n=s.length();

        int maxlen=0;
        for(String str:dict){
            int len=str.length();
            if(len>maxlen){
                maxlen=len;
            }
        }

        //state;
        boolean[] cut=new boolean[n+1];

        //Initialize:
        cut[0]=true;

        //function:
        for(int i=1;i<=n;i++){
            cut[i]=false;
            for(int lastwordlength=1;
                    lastwordlength<=maxlen && lastwordlength<=i;
                    lastwordlength++){

            String word=s.substring(i-lastwordlength, i);
                if(cut[i-lastwordlength] && dict.contains(word)){
                    cut[i]=true;
                    break;
            }
        }
    }
        return cut[n];


    }

Last updated