139. 单词拆分
知识点:字典树,字符串匹配,动态规划
时间:2020年11月1日
题目链接:https://leetcode-cn.com/problems/word-break
题目
给定一个非空字符串 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
解法
用到了字典树(用来判断前缀、后缀,在这里比hash表速度更快):
- 如果头节点的next对应的字符未创建,创建空间,节点往下走
- 等到整个字符输入完成后,标记下已结束
此题用来判断后缀,所以倒着入站,looked—>dekool
root节点
-> [d,0]->[e,0]->[k,0]->[e,0]->[d,1]
-> [t,0]->[s,0]->[u,0]->[j,1]
-> [e,0]->[k,0]->[i,0]->[l,1]
-> [r,0]->[e,0]->[h,1]->[t,0]->[o,0]->[r,0]->[b,1]
最后字典树就变了这样,其中红色节点代表字符结束
- 动态规划,走到这个点看看能否用之前的加上这个字符拼成
举例:
apple pen apple
10000 100 10000 1
代码
#include <stdio.h>
#include <iostream>
#include <vector>
#include <unordered_set>
using namespace std;
/*
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
unordered_set<string> wordDictSet = unordered_set <string> ();
for (string word: wordDict) {
wordDictSet.insert(word);
}
vector<bool> dp = vector <bool> (s.size() + 1,false);
dp[0] = true;
for (int i = 1; i <= s.size(); ++i) {
for (int j = 0; j < i; ++j) {
if (dp[j] && wordDictSet.find(s.substr(j, i - j)) != wordDictSet.end()) {
dp[i] = true;
break;
}
}
}
return dp[s.size()];
}
};
*/
class Trie {
public:
Trie* next[26] = {nullptr};
bool isend;
Trie(){
isend = false;
}
void insert(string s){
Trie *tmp = this;
for(int i = s.size()-1;i >= 0;i--){
int idx = s[i] - 'a';
if(tmp ->next [idx] == nullptr){
tmp -> next[idx] = new Trie();
}
tmp = tmp -> next[idx];
}
tmp -> isend = true;
}
};
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
Trie* root = new Trie();
int n = s.length();
vector<int> dp(n+1,0);
for(string s : wordDict)
root->insert(s);
dp[0] = true;
for(int i = 1;i <= n;i++){
Trie* tmp = root;
for(int j = i-1;j >= 0;j--){
int x = s[j] - 'a';
if(tmp->next[x] == nullptr){
break;
}
else if (tmp->next[x]->isend == true && dp[j]){
dp[i] = true;
break;
}
tmp = tmp->next[x];
}
}
return dp[n];
}
};
int main()
{
vector<string> d(10);
d[0] = "aaaa";d[1]="aaa";
string st = "aaaaaaa";
Solution s ;
cout<<s.wordBreak(st, d);
return 0;
}
今天也是爱zz的一天哦!