Word Break

题目
Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words. You may assume the dictionary does not contain duplicate words.

For example, given

s = "leetcode",
dict = ["leet", "code"].

Return true because "leetcode" can be segmented as "leet code".

分析
第一眼看到这个题目,或许最直觉的方法就是,把s分成若干份,这样有很多种分法,对每一种分法,检查每一份word是否在word list里。

但是这样显然特别慢,可以有(n choose 1) + (n choose 2) + ... (n choose n)种分法。
下面用dp思路解决这个问题
定义dp[i] = true when s[i...n] has a word break, false otherwise
base case是dp[i] = whether s[i...n] is in word list, for all i

s: |____________|_______|
1........................k.............n

假设我们已经知道了dp[k+1...n], dp[k+2, ...n], ... dp[n],那么如何知道[k...n]之间是否有word break?

for i = k to n
  dp[k] = true if s[k...i] is a word in word list and dp[i+1] is true

如果从index k到i之间的string在word list里面,而且我们已经知道从index i+1 到n之间的string有word break,那么就可以确定s[k...n]之间是否有word break了。

因为basecase是dp[n], 有了dp[n]可以计算dp[n-1], dp[n-2], 进而计算出dp[1]。也就是可以计算出s[1...n]之间是否有word break。

以上的解释是以string的index是从1开始算的,代码里是以0开始,请注意区分一下

public boolean wordBreak(String s, List<String> wordDict) {
        int n = s.length();
        HashMap<String, Boolean> wordMap = new HashMap<String, Boolean>();

        // Put each word into wordMap for quick lookup
        for(String word : wordDict) {
            wordMap.put(word, true);
        }
        // dp array
        boolean[] hasWordBreak = new boolean[n+1];

        // Does string from index n-1 (to n-1) have a word break?
        for(int i = n-1; i >= 0; i--) {
            String curr_word = s.substring(i, n);
            hasWordBreak[i] = wordMap.get(curr_word) != null;
        }

        hasWordBreak[n] = false;

        for(int k = n-1; k >= 0; k--) {
            for(int i = k; i < n; i++) {
                String curr_word = s.substring(k, i + 1);
                if(wordMap.get(curr_word) != null && hasWordBreak[i + 1]) {
                    hasWordBreak[k] = true;
                    break;
                }

            }
        }

        return hasWordBreak[0];
    }

时间复杂度为O(n^2), 因为主要的计算发生在一个二维循环里
这道题如果用常规的方法来做肯定会超时

回头看看这篇文章如何解这道题
http://www.geeksforgeeks.org/dynamic-programming-set-32-word-break-problem/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容