Word Break

406 篇文章 0 订阅
406 篇文章 0 订阅

1,题目要求

Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words.

Note:

  • The same word in the dictionary may be reused multiple times in the segmentation.
  • You may assume the dictionary does not contain duplicate words.

Example 1:
Input: s = "leetcode", wordDict = ["leet", "code"]
Output: true
Explanation: Return true because “leetcode” can be segmented as “leet code”.

Example 2:
Input:s = "applepenapple", wordDict = ["apple", "pen"]
Output:true
Explanation: Return true because “applepenapple” can be segmented as “apple pen apple”.
Note that you are allowed to reuse a dictionary word.

Example 3:
Input:s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
Output: false

给定非空字符串s和包含非空字列表的字典wordDict,确定s是否可以被分段为一个或多个字典单词的空格分隔序列。

注意:

  • 字典中的相同单词可以在分段中多次重复使用。
  • 您可以假设词典不包含重复的单词。

2,题目思路

对于这道题,题目是给定一个字符串和一个“字典”,字典中有一系列的单词。题目的要求是判断这个字符串是否可以划分成一系列的单词,其中这些单词都在字典中出现过。

需要注意的是,这里的划分是一个全划分的关系,即:
假如划分成了三个单词A、B、C,那么:

  • A∩B∩C = ∅
  • A∪B∪C = s

于是,对于这个问题,我们按照顺序将字符串s划分成所有可划分的形式,以判断条件是否成立。而对于这种问题,一般来说我们使用动态规划的思路是比较正确的思路。

还是那句话,动态规划的思想就是划分子问题,找到正确的子问题——DP[i]是问题的关键。

在这个问题上,我们设置的DP[i]所表示的含义是:

  • index = 0index = i的字符串s的子串tmp,是否满足 “子串可以划分成特定单词,使得它们都出现在字典中”
  • 如果满足条件,DP[i] = true,否则,就为false;默认状态下,都为false
  • 如果DP[j] = true,判断DP[j + (i-j)]是否为true;其中,0≤j≤i-1
  • DP[0] = true,最后判断DP[s.size()]是否是true即可。

其中,还有一些技术细节:
1,substr
在C++中,取一个字符串的子串的方法:
string substr (size_t pos = 0, size_t len = npos) const;

产生子串
返回一个新建的初始化为string对象的子串的拷贝string对象。

子串是,在字符位置pos开始,跨越len个字符(或直到字符串的结尾,以先到者为准)对象的部分。

参考文章:
C++ string substr()

2,vector中find的使用
不同于map(map有find方法),vector本身是没有find这一方法,其find是依靠algorithm来实现的。

#include <iostream>
#include <algorithm>
#include <vector>
 
int main()
{
    using namespace std;
 
    vector<int> vec;
 
    vec.push_back(1);
    vec.push_back(2);
    vec.push_back(3);
    vec.push_back(4);
    vec.push_back(5);
    vec.push_back(6);
 
    vector<int>::iterator it = find(vec.begin(), vec.end(), 6);
 
    if (it != vec.end())
        cout<<*it<<endl;
    else
        cout<<"can not find"<<endl;
 
    return 0;
}

参考文章:
c++中vector find使用

3,代码实现

int x = []() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    return 0;
}();

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        //因为题目已经给定s和wordDict都是non-empty
        //因此就不需要检测输入了
        
        vector<bool> DP(s.size()+1, false);
        DP[0] = true;
        
        for(int i = 1;i<=s.size();i++){
            for(int j = i-1;j>=0;j--){
                if(DP[j]){
                    string tmp = s.substr(j, i-j);
                    if(find(wordDict.begin(), wordDict.end(), tmp)!= wordDict.end()){
                        DP[i] = true;
                        break;
                    }
                }
            }
        }
        
        return DP[s.size()];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值