Problem

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

example: "abc"

f[3] = f["abc"]

f[2] = f["ab"]

f[1] = f["a"]

f[0] = f[""]

思路:

  • 一个长度为n的单词, 假设i 为某一位, 能否切分成词典里面的词, 取决于 长度(0 到 i) 子串是否能成功切分, 并且(i 到 n) 子串是词典里面的单词.
  • 所以我们定义
  • state:
    • f[i]: 前i个字符能被切分为dict words
    • size: n + 1
  • function:
    • f[i]: j < i, f[j] && substring(i, n) in dictionary
  • initialize:
    • f[0]: true, empty string
  • answer:
    • f[n]
  • 时间复杂度
    • O(l * n^2)
    • l is the average length of words in dict
    public boolean wordBreak(String s, Set<String> dict) {
        if (s == null) {
            return false;
        }  

        boolean[] dp = new boolean[s.length() + 1];

        dp[0] = true;

        for (int i = 1; i <= s.length(); i++) {
            for (int j = 0; j < i; j++) {
                if (dp[j] == false) continue;

                if (dict.contains(s.substring(j, i))) {
                    dp[i] = true;
                    break;
                }
            }
        }

        return dp[s.length()];
    }

Optimization

假设给定的字符串很长, j 所取的长度便会很大, 导致时间复杂度很高. 于是我们遍历字典, 找到最长的单词长度

i - j <= maxWordLength, 并且j 从 i - 1开始取, j >= 0

时间复杂度: O(n * l ^ 2)

    public boolean wordBreak(String s, Set<String> dict) {
        if (s == null) {
            return false;
        }  

        boolean[] dp = new boolean[s.length() + 1];

        dp[0] = true;

        int maxLen = getMaxLength(dict);

        for (int i = 1; i <= s.length(); i++) {
            for (int j = i - 1; i - j <= maxLen && j >= 0; j--) {
                if (dp[j] == false) 
                    continue;

                if (dict.contains(s.substring(j, i))) {
                    dp[i] = true;
                    break;
                }
            }
        }

        return dp[s.length()];
    }

    private int getMaxLength(Set<String> dict) {
        int res = Integer.MIN_VALUE;
        for (String s: dict) {
            res = Math.max(res, s.length());
        }
        return res;
    }

results matching ""

    No results matching ""