一、题意
给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s。(不需要所有单词都能用上)
二、解法
解法:
动态规划
dp[i]
表示前i个字符是否能拆分成若干个出现在字典中的单词。
对于dp[i]
由其子字符串dp[j](j<i)
和到i-1的字符串是否能组成一个单词决定。
用map存储wordDict单词
dp[i]=dp[j]&&map.count(s.substr(j,i-j))
i-j超过wordDict中单词的最大长度,可以剪枝。
时间复杂度:
O
(
n
2
)
O(n^2)
O(n2)
空间复杂度:
O
(
n
)
O(n)
O(n)
三、代码
解法:
bool wordBreak(string s, vector<string>& wordDict) {
map<string,int> wordMap;
int maxLength = 0;
for(int i=0;i<wordDict.size();i++){
wordMap[wordDict[i]]=1;
maxLength = max(maxLength,(int)wordDict[i].size());
}
vector<int> dp(s.size()+1,0);
dp[0]=1;
for(int i=1;i<=s.size();i++){
for(int j=0;j<i;j++){
if(i-j<=maxLength ){
dp[i]=dp[j]&&wordMap.count(s.substr(j,i-j));
// printf("%d %d %d %d %d\n",i,j,j,i,dp[i]);
}
if(dp[i]){
break;
}
}
}
/* for(int i=0;i<=s.size();i++){
cout<<dp[i]<<" ";
}*/
return dp[s.size()];
}
四、总结
一开始设置了二维数组,以dp[i][j]
表示i到j是否能找到单词对应,但觉得会超时,而且可能存在重复的情况。dp[j](j<i)
的判断情况,在dp[i]
中也会判断一遍,所以可以dp[j]
来决定dp[i]
,最重要的是对后面部分判断,是否能匹配到一个单词。自己写的话,估计会用递归,把后面所有可能有单词的情况,每次这样会存在重复性。这一题找到哪些重复操作的点,就能写出来。