给你一个字符串 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
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
unordered_set<string> dict;//存储字典,方便判断当前字符串是否为给定的单词
for(int i=0;i<wordDict.size();i++)
dict.insert(wordDict[i]);
//s有n个字符,有n+1个切割点,即0~n
vector<bool> dp(s.size()+1,false);
dp[0]=true;//边界,s为空串
//dp[i]=dp[j]+isWord(s[j,i-1])
//从1开始枚举i,内层循环判断i之前的字符能否全部拆分成给定单词
for(int i=1;i<=s.size();i++)
{
for(int j=0;j<i;j++)
{//如果dp[j]为true表示j之前字符可以拆分成单词,此时如果j~i-1也是单词则为true
if(dp[j]&&dict.find(s.substr(j,i-j))!=dict.end())
{
dp[i]=true;
break;
}
}
}
return dp[s.size()];//返回结果
}
};
给定一个字符串 s 和一个字符串字典 wordDict ,在字符串 s 中增加空格来构建一个句子,使得句子中所有的单词都在词典中。以任意顺序 返回所有这些可能的句子。
注意:词典中的同一个单词可能在分段中被重复使用多次。
示例 1:
输入:s = “catsanddog”, wordDict = [“cat”,“cats”,“and”,“sand”,“dog”]
输出:[“cats and dog”,“cat sand dog”]
示例 2:
输入:s = “pineapplepenapple”, wordDict = [“apple”,“pen”,“applepen”,“pine”,“pineapple”]
输出:[“pine apple pen apple”,“pineapple pen apple”,“pine applepen apple”]
解释: 注意你可以重复使用字典中的单词。
示例 3:
输入:s = “catsandog”, wordDict = [“cats”,“dog”,“sand”,“and”,“cat”]
输出:[]
来源:力扣(LeetCode)
class Solution {
public:
vector<string> wordBreak(string s, vector<string>& wordDict) {
//此处与题一完全一致
unordered_set<string> dict;
for(int i=0;i<wordDict.size();i++)
dict.insert(wordDict[i]);
//word[i][j]为true表示字符串s[i,j]是一个单词
vector<vector<bool>> word(s.length()+1,vector<bool>(s.length(),false));
vector<bool> dp(s.size()+1,false);
dp[0]=true;//边界,s为空串
for(int i=1;i<=s.size();i++)
{
for(int j=0;j<i;j++)
{
if(dp[j]&&dict.find(s.substr(j,i-j))!=dict.end())
{//第一处不同,由于要返回全部解,此处在找到一种情况后不能break,还要继续找
dp[i]=true;
//j是字符串子串的起点字符的下标,i-1是终点字符的下标,且该子串是一个单词
word[j][i-1]=true;
}
}
}
//path储存一个结果,result储存所有结果
vector<string> path,result;
//只有s可以分割为单词串时才搜索全部结果
if(dp[s.size()]) dfs(s,word,s.length(),path,result);
return result;
}
//搜索组装所有句子
//0~index表示当前还未被搜索的字符,在这些字符中寻找s[i,index-1]为单词的i,然后进行下一次递归
void dfs(const string &s, const vector<vector<bool>> &word, int index,vector<string> &path,vector<string> &result)
{
if(index==0)//递归边界,找到一种情况,将path转化为字符串
{
string tmp;
for(int i=path.size()-1;i>0;i--)
tmp+=(path[i]+" ");
tmp+=path[0];
result.push_back(tmp);
return;
}
//尝试所有可能的s[i,index-1]
for(int i=0;i<index;i++)
{
if(word[i][index-1])//如果是一个单词就将它加入到path中,进行下一次递归
{
path.push_back(s.substr(i,index-i));
dfs(s,word,i,path,result);
path.pop_back();
}
}
}
};