LeetCode 140. Word Break II

90 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第40天,点击查看活动详情

LeetCode 140. Word Break II

给定一个字符串 s 和一个字符串字典 wordDict ,在字符串 s 中增加空格来构建一个句子,使得句子中所有的单词都在词典中。以任意顺序 返回所有这些可能的句子。

注意: 词典中的同一个单词可能在分段中被重复使用多次。

 

示例 1:

输入: s = "catsanddog", wordDict = ["cat","cats","and","sand","dog"]
输出: ["cats and dog","cat sand dog"]

示例 2:

输入: s = "pineapplepenapple", wordDict = ["apple","pen","applepen","pine","pineapple"]
输出: ["pine apple pen apple","pineapple pen apple","pine applepen apple"]
解释: 注意你可以重复使用字典中的单词。

示例 3:

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

 

提示:

  • 1 <= s.length <= 20
  • 1 <= wordDict.length <= 1000
  • 1 <= wordDict[i].length <= 10
  • s 和 wordDict[i] 仅有小写英文字母组成
  • wordDict 中所有字符串都 不同

算法

(动态规划 + 递归枚举)
按照 Word Break 的动态规划思路,求出 f 数组,f(i) 表示 [0, i] 是否可以被完整分割。
根据 f 数组,从位置 n 开始进行递归枚举所有可能分割的方式。枚举时,只需要判断 f(i) 是否可能从 f(j) 转移过来的,若可能,则递归到位置 j。

时间复杂度

动态规划的时间复杂度为 O(n3)。
递归枚举的时间复杂度与方案数相等,为指数级。

ac 代码

class Solution {
public:

    void dfs(int i, const vector<bool>& f, const string &s,
             const unordered_set<string>& wordSet,
             vector<string>& cur_string, vector<string>& ans) {
        if (i == 0) {
            string tmp = "";
            for (int k = cur_string.size() - 1; k >= 0; k--) {
                tmp += cur_string[k];
                if (k > 0)
                    tmp += " ";   
            }
            ans.push_back(tmp);
            return;
        }
        for (int j = 0; j < i; j++) {
            string cur = s.substr(j, i - j);
            if (f[j] && wordSet.find(cur) != wordSet.end()) {
                cur_string.push_back(cur);
                dfs(j, f, s, wordSet, cur_string, ans);
                cur_string.pop_back();
            }
        }
    }

    vector<string> wordBreak(string s, vector<string>& wordDict) {
        int n = s.length();
        unordered_set<string> wordSet(wordDict.begin(), wordDict.end());
        vector<bool> f(n + 1, false); // 为了方便,f 数组的下标从 1 开始。
        f[0] = true;
        for (int i = 1; i <= n; i++)
            for (int j = 0; j < i; j++) {
                string cur = s.substr(j, i - j);
                if (wordSet.find(cur) != wordSet.end())
                    f[i] = f[i] | f[j];
            }
        vector<string> ans;
        vector<string> cur_string;
        dfs(n, f, s, wordSet, cur_string, ans);
        return ans;
    }
};