2022-11-18 17:02阅读: 24评论: 0推荐: 0

力扣-139-单词拆分

前缀树模板题?

直接看题解,明明是前缀树标签,却只给了动态规划

前缀树

我试图用208前缀树的直接思路解决这个问题

class Trie {
private:
vector<Trie*> children;
bool isEnd;
public:
Trie() :children(26), isEnd(false) {}
void insert(string word) {
Trie* node = this;
for (char ch : word) {
ch -= 'a';
if (node->children[ch] == nullptr)
node->children[ch] = new Trie();
node = node->children[ch];
}
node->isEnd = true;
}
bool wordBreak(string input) {
Trie* node = this;
for (int i = 0; i < input.length(); i++) {
input[i] -= 'a';
if (node->children[input[i]] == nullptr) return false;
node = node->children[input[i]];
if (node->isEnd && i != input.length() - 1)node = this;
}
return node->isEnd;
}
};
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
Trie trie;
for (string str : wordDict) trie.insert(str);
return trie.wordBreak(s);
}
};

但是卡在了这两个测试用例

"aaaaaaa"
["aaaa","aa"]

"aaaaaaa"
["aaaa","aaa"]

还是逃不掉动态规划吗

我又改成这样

bool wordBreak(string input,int start) {
Trie* node = this;
for (int i = start; i < input.length(); i++) {
input[i] -= 'a';
if (node->children[input[i]] == nullptr) return false;
node = node->children[input[i]];
if (node->isEnd && i != input.length() - 1)
if (wordBreak(input, i + 1))return true;
}
return node->isEnd;
}

然后被预判了,果断超时

动态规划

思路是判断i个位置,以strArr[i]结尾的字符串是否可以由状态转移方程递归出来
而每一次判断都需要从头遍历j位置,看以j做分隔的字符串能否由字典中的字符串构成

class Trie {
private:
vector<Trie*> children;
bool isEnd;
public:
Trie() :children(26), isEnd(false) {}
void insert(string word) {
Trie* node = this;
for (char ch : word) {
ch -= 'a';
if (node->children[ch] == nullptr)
node->children[ch] = new Trie();
node = node->children[ch];
}
node->isEnd = true;
}
bool search(string word) {
Trie* node = this;
for (char ch : word) {
ch -= 'a';
if (node->children[ch] == nullptr)
return false;
node = node->children[ch];
}
return node->isEnd;
}
};
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
Trie trie;
for (string str : wordDict) trie.insert(str);
int len = s.length();
vector<bool> dp(len + 1);
dp[0] = 1;
for (int i = 1; i <= s.length(); i++) {
for (int j = 0; j < i; j++) {
if (dp[j] && trie.search(s.substr(j, i - j))) {
dp[i] = true;
break;
}
}
}
return dp[len];
}
};

自己写不如用现成的系列,本质还是动态规划,只是前缀树代替了set而已

class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
Trie trie;
int maxLen = wordDict[0].length();
for (string str : wordDict) {
trie.insert(str);
if (str.size() > maxLen) maxLen = str.size();
}
int len = s.length();
vector<bool> dp(len + 1);
dp[0] = 1;
for (int i = 1; i <= s.length(); i++) {
for (int j = 0; j < i; j++) {
// 剪枝:如果i-j的字符串长度已经大于了字典中最长字符串的长度
if (i - j > maxLen) continue;
if (dp[j] && trie.search(s.substr(j, i - j))) {
dp[i] = true;
break;
}
}
}
return dp[len];
}
};

加上剪枝,情况好了很多

本文作者:YaosGHC

本文链接:https://www.cnblogs.com/yaocy/p/16903003.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   YaosGHC  阅读(24)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起