LeetCode139. 单词拆分

题目

参考代码随想录

分析

本题可看出为完全背包问题。关键是dp[i]表示什么?dp[i] == true 表示长度为 i  的字符串可以词典中的单词完全划分。

确定递推公式 :

if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。

初始化:

为了不使初始化覆盖结果,所以dp数组初始化为false,但dp[0]为true,否则后面将全为false。

确定遍历顺序:

完全背包的题目可以先遍历物品再遍历背包或者反过来,但要保证内循环为正序(因为可以重复取同一物品)。但是本题有特殊性,本题的字符串为背包,词典中的单词为物品。应该先遍历背包再遍历物品,因为字符串本身是由词典中的单词按照特定顺序组成的,说白了,就是把物品装进背包是有顺序的。

代码

 1 class Solution {
 2 public:
 3     bool wordBreak(string s, vector<string>& wordDict) {
 4         unordered_set<string>st(wordDict.begin(),wordDict.end());//去重加查找单词
 5         vector<bool>dp(s.length()+1,false);
 6         dp[0] = true;//若不设为真,后面全为false
 7         //先遍历背包再遍历物品
 8         for(int i = 1;i <= s.length();i++){
 9             for(int j = 0;j < i;j++){
10                 string word = s.substr(j,i-j);
11                 if(st.find(word)!=st.end() && dp[j] == true)
12                     dp[i] = true;
13             }
14         }
15         return dp[s.length()];
16     }
17 };

 采用回溯+记忆化数组

class Solution {
public:
    bool backtracking(const string &s,const unordered_set<string> &st,vector<int> &visit,int startIndex){
        if(startIndex >= s.size()){
            return true;
        }
        if(visit[startIndex] != -1) return visit[startIndex]; //若被搜索过,直接返回结果
        //遍历所有分割方式
        for(int i = startIndex;i < s.size();i++){
            if(st.find(s.substr(startIndex,i-startIndex+1)) != st.end() && backtracking(s,st,visit,i+1)){
                visit[startIndex] = 1;
                return true;
            }
        }
        //所有分割方式遍历不能返回true,就意味着找不到分割方式使得字符串拆分成字典中的单词
        visit[startIndex] = 0;//以startIndex开始划分的子串不可拆分
        return false;
    }
    bool wordBreak(string s, vector<string>& wordDict) {
        unordered_set<string>st(wordDict.begin(),wordDict.end());//去重加查找单词
        vector<int>visit(s.size(),-1);//记忆化搜索
        return backtracking(s,st,visit,0);

    }
};

 

posted @ 2021-02-18 21:54  Uitachi  阅读(61)  评论(0编辑  收藏  举报