Word Break

在这里插入图片描述
解析 :
题意:单词划分,将字符串分解成多个单词,每个单词都要出现在字典当中,如果存在,返回true,否则返回false
分析:本题并没有要求我们将每一种满足划分条件的列出来,只需要找到一种情况即可。要保证划分后的每一个单词都要出现在字典当中,即意味着后面划分的单词一定是基于****前面划分的单词基础之上,即下一个状态依赖于上一个状态,可以利用动态规划进行求解,同时也可以采用带记忆状态的DFS进行求解,先讨论DFS,首先我们并不知道要划分成多少个单词,所以就可以先找到第一个存在字典的单词,然后基于第一个划分的单词,继续往下搜索,寻找满足第二个划分的单词,再接着搜索第三个…直到到达字符串的尾部
基于以上分析,用记忆数组record记录已经搜索过的状态,record[i]表示起始位置i到n满足划分的条件,start表示当前搜索的起始位置,i表示终止位置
1.临界条件:
搜索的起始位置到达字符串的尾部,即满足划分条件,返回true;
当前起始位置搜索过,返回搜索过的状态;
2.查找[start, i-start]子串是否在字典当中,若在,从上一个字串的结束位置i开始往下搜索,如果一直满足状态,则划分成功,返回true,否则,回溯到上一个状态
例如:“leetcode”

  1. 先查找"leet",然后继续往下搜索"code",依次往上返回true
class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        set<string> wordSet(wordDict.begin(), wordDict.end()); //存储到hashtable,方便查找字典当中的元素
        vector<int> record(s.length(), -1);
        return DFS(s, wordSet, 0, record);
    }
    
    bool DFS(string& s, set<string>& wordDict, int start, vector<int>& record){
        if (start >= s.length()) return true; //搜索到字符串起始位置大于长度,即满足划分条件
        if (record[start] != -1) return record[start]; //已经搜索过这个状态
        for (int i = start + 1; i <= s.length(); ++i){
            if (wordDict.count(s.substr(start, i-start)) && DFS(s, wordDict, i, record)){ //满足划分的条件,继续查找下一个单词
                return record[start] = 1; //标记当前的状态
            }
        }
        
        return record[start] = 0; //不满足划分的条件,记录当前的状态
    }
};

动态规划解法:
dp[i]表示[0, i]字串是否存在字典,因为动态规划数组是从前往后推进的,所以后面的状态一定依赖于前面的状态,即前面的状态已经求解出来
1.先判断前面的状态是否存在于字典当中
2.若存在,继续判断后面的字串[j, i-1]是否在字典当中,若存在,则dp[i]满足划分条件

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        set<string> wordSet(wordDict.begin(), wordDict.end());
        vector<bool> dp(s.length() + 1, false);
        dp[0] = true;
        for (int i = 0; i < dp.size(); ++i){
            for (int j = 0; j < i; ++j){
                if (dp[j] && wordSet.count(s.substr(j, i - j))){
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp.back();
    }
};

[1]https://www.cnblogs.com/grandyang/p/4257740.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值