题目地址:https://oj.leetcode.com/problems/word-break-ii/
题意:给一个字典和一个字符串,用字典将字符串中的单词全部提取出来,返回所有可行的结果
解题思路:dp+针对特殊case的处理,这里二维dp[i][j](i表示从第i个字符开始,j表示字符串的长度)表示子串s是否在字典内,最后dfs出答案既可。
特殊case:
Input:
“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab”, [“a”,”aa”,”aaa”,”aaaa”,”aaaaa”,”aaaaaa”,”aaaaaaa”,”aaaaaaaa”,”aaaaaaaaa”,”aaaaaaaaaa”]
对于这个case,如果dfs枚举答案时从前往后枚举的话就会超时,所以我就从后往前枚举了。
要点:复习了dp的概念,有时间的话再去复习下揹包九讲,毕竟很久没碰过dp了。
#include<unordered_set>
using namespace std;
class Solution {
vector<bool> *dp;
vector<string> matchStr;
vector<string> ans;
public:
vector<string> wordBreak(string s, unordered_set<string> &dict) {
int len = s.size();
dp = new vector<bool>[len];
for(int i=0; i<len; ++i){
for(int j=i; j<len; ++j){
string str = s.substr(i,j-i+1);
dp[i].push_back(match(str,dict));
}
}
checkAns(len-1,s);
return ans;
}
bool match(string& s1,unordered_set<string> &dict){
if(dict.find(s1)==dict.end()){
return 0;
}
else{
return 1;
}
}
void checkAns(int endPos,string& s){
if(endPos == -1){
getAns();
return;
}
for(int len = 0; len<endPos+1; ++len){
if(dp[len][endPos-len]){
matchStr.push_back(s.substr(len,endPos-len+1));
checkAns(len-1,s);
matchStr.pop_back();
}
}
}
void getAns(){
string str;
int size = matchStr.size();
for(int i=size-1; i>=0;--i){
str += matchStr[i];
if(i != 0){
str += " ";
}
}
ans.push_back(str);
}
};