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 = 0
到index = 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()];
}
};