【區間 dp】B019_LC_單詞拆分(向前看 / 優化邊界)

一、Problem

給定一個非空字符串 s 和一個包含非空單詞列表的字典 wordDict,判定 s 是否可以被空格拆分爲一個或多個在字典中出現的單詞。

說明:

  • 拆分時可以重複使用字典中的單詞。
  • 你可以假設字典中沒有重複的單詞。
輸入: s = "applepenapple", wordDict = ["apple", "pen"]
輸出: true
解釋: 返回 true 因爲 "applepenapple" 可以被拆分成 "apple pen apple"。
注意你可以重複使用字典中的單詞。

輸入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
輸出: false

二、Solution

方法一:dp

  • 定義狀態
    • f[i]f[i] 表示字符串 ss 的前 ii 個字符能否拆分成一個或多個在字典中出現的單詞
  • 思考初始化:
    • f[0]=truef[0] = true,我是試了下空串才知道的爲 true,可能是…
  • 思考狀態轉移方程
    • 如果存在 f[l]=true && set.contains(sub))f[l] = true\ \&\&\ set.contains(sub)),則有 f[r]=truef[r] = true 表示如果子串 s[0:r]s[0:r] 能在字典中找到的前提條件是,子串 s[0:l]s[0:l] 在字典中,且 s[l:r]s[l:r] 也在字典中
  • 思考輸出f[n]f[n]
class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        Set<String> st = new HashSet<>(wordDict);
        int n = s.length();
        boolean f[] = new boolean[n+1];
        f[0] = true;

        for (int r = 1; r <= n; r++)
        for (int l = 0; l < r; l++) {
            if (f[l] && st.contains(s.substring(l, r))) {
                f[r] = true;
                break;
            }
        }
        return f[n];
    }
}

複雜度分析

  • 時間複雜度:O(n2)O(n^2)
  • 空間複雜度:O(n)O(n)

方法二:優化

  • 第一:如果 wordDict 中的單詞長度都比 1 大,那麼右邊界 rr 從 1 開始也就變得有點雞肋了,所以 rr 可從 wordDict 的最短單詞長度 mi 開始
  • 第二:如果 rlr-l 很大,而字 wordDict 中的單詞最大長度都比 rlr-l 要短,那麼此時 s[l:r]s[l:r] 這個子串也肯定在 wordDict 找不到,所以 l 可以從最大 wordDict 中的最大單詞長度的其實位置開始 rmxr-mx

基於以上兩個問題,我們可把代碼改爲:

class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        Set<String> st = new HashSet<>(wordDict);
        int n = s.length(), mi = 0, mx = -1;
        boolean f[] = new boolean[n+1];
        f[0] = true;
        for (String w : st) {
            if (w.length() > mx) 			mx = w.length();
            if (mi == 0 || mi > w.length()) mi = w.length();
        }

        for (int r = mi; r <= n; r++)
        for (int l = Math.max(0, r-mx); l < r; l++) {
            if (f[l] && st.contains(s.substring(l, r))) {
                f[r] = true;
                break;
            }
        }
        return f[n];
    }
}

複雜度分析

  • 時間複雜度:O(n2)O(n^2)
  • 空間複雜度:O(n)O(n)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章