//给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。 
//
// 说明: 
//
// 
// 拆分时可以重复使用字典中的单词。 
// 你可以假设字典中没有重复的单词。 
// 
//
// 示例 1: 
//
// 输入: s = "leetcode", wordDict = ["leet", "code"]
//输出: true
//解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。
// 
//
// 示例 2: 
//
// 输入: s = "applepenapple", wordDict = ["apple", "pen"]
//输出: true
//解释: 返回 true 因为 "applepenapple" 可以被拆分成 "apple pen apple"。
//     注意你可以重复使用字典中的单词。
// 
//
// 示例 3: 
//
// 输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
//输出: false
// 
// Related Topics 动态规划 
// 👍 854 👎 0

/*
* 139 单词拆分
* 2021-03-04 19:11:28
* @author oxygenbytes
*/ 
#include "leetcode.h" 
//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
public:
    unordered_set<string> us;
    unordered_map<string, bool> exist;
    bool wordBreak(string s, vector<string>& wordDict) {
        us = unordered_set<string>(wordDict.begin(), wordDict.end());
        return dfs(s);
    }
    bool dfs(string s){
        if(exist.count(s)) return exist[s];

        if(us.count(s))  return exist[s] = true;

        for(int i = 0;i < s.size();i++){
            string temp = s.substr(0, i);
            if(us.count(temp)){
                if(dfs(s.substr(i)))
                    return exist[s] = true;
            }
        }
        return exist[s] = false;
    }
};
//leetcode submit region end(Prohibit modification and deletion)