单词拆分:给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。
说明:
拆分时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-break
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
分析:利用动态规划,将字符串的处理看成每个小问题的同样处理,也就是把一个字符串拆分成s1和s2,如果s1和s2都存在于字典中,那么s就是满足要求的。利用n+1的dp数组,初始dp[0]要为true,其他为false,利用i来指示当前子串的位置,j代表该子串的拆分位置,即拆成了s(0,j)和s(j+1,i)。只要dp[j]为true,我们就可以判断substr(j+1,i)这个子串是否处于字典中,然后对dp[i]进行赋值。
#include<algorithm>
class Solution {
public:
/*bool wordBreak(string s, vector<string>& wordDict) {
//先试一下回溯法
return wordBreakCore(s,wordDict,0);
}
bool wordBreakCore(string s,vector<string>& wordDict,int index){
if(index == s.size())return true;
//主体
int n = s.size();
for(int i=1;i<=n-index;i++){
if(find(wordDict.begin(),wordDict.end(),
s.substr(index,i)) != wordDict.end()){
//查找到了
//string newStr = s.substr(s,s+i);
bool result = wordBreakCore(s,wordDict,index+i);
if(result==true)return true;
}
}
return false;
}*/
bool wordBreak(string s, vector<string>& wordDict) {
//动态规划呢
int n = s.size();
vector<bool> dp(n+1,false);
dp[0] = true;
for(int i=1;i<=n;i++){
//这个动态规划的思想是,按子串来找到符合字典的拆分位置
//i表示子串的结束位置,j表示子串的拆分位置
for(int j=0;j<i;j++){
if(dp[j] && find(wordDict.begin(),wordDict.end(),
s.substr(j,i-j)) != wordDict.end()){
dp[i] = true;
break;
}
}
}
/*for(int i=0;i<=n;i++)
cout<<dp[i]<<' '<<endl;
cout<<endl;*/
return dp[n];
}
};```