Word Rectangle:给定一个字典,使用字典中的单词组成一个最大的矩阵,该矩阵中每行和每列都是字典中的单词,单词可以重复使用。
最喜欢这种题了,反正也没什么取巧的方法,直接搜索就好了,主要看代码能力。因为要返回最大的矩阵,所以我们从最大的边长开始,慢慢缩小搜索边长。返回类型为vector<string>,根据其特点,每次添加矩阵的一行较为方便,然后在新得到的部分矩阵中,去检查每一列是否是字典中单词的前缀即可。
题解中的很多方法都是使用整个字典构建的Trie树,不过我感觉这样子不利于剪枝,所以我借鉴了书上的方法,将字典中的单词按照长度进行了分组,用Group表示,每个Group中包含两个成员,一个unordered_set<string> WordSet用来记录单词,另一个Trie root用来进行前缀查找。
每次搜索都需要指定这次要搜索的矩阵的length和height。当在矩阵中添加新的一行后,直接查找每一列是否在Group[height]的root中即可。
class Solution {
private:
struct TrieNode
{
char ch;
array<shared_ptr<TrieNode>, 26> Children;
TrieNode(char c = '\0') : ch(c){}
};
struct Trie
{
shared_ptr<TrieNode> RootPointer;
Trie(){ RootPointer = make_shared<TrieNode>(); }
void addString(const string &str)
{
shared_ptr<TrieNode> NodePointer = RootPointer;
for(char c : str)
{
if(NodePointer->Children[c - 'a'] == nullptr){
NodePointer->Children[c - 'a'] = make_shared<TrieNode>(TrieNode(c));
}
NodePointer = NodePointer->Children[c - 'a'];
}
}
bool contain(const vector<string> &rect, const size_t col)
{
shared_ptr<TrieNode> NodePointer = RootPointer;
for(const string &word : rect)
{
char c = word[col];
if(NodePointer->Children[c - 'a'] == nullptr) return false;
else NodePointer = NodePointer->Children[c - 'a'];
}
return true;
}
};
struct Group
{
unordered_set<string> WordSet;
Trie root;
bool empty(){ return WordSet.empty(); }
void addWord(const string &word)
{
WordSet.insert(word);
root.addString(word);
}
bool partialContain(const vector<string> &rect, const size_t col){ return root.contain(rect, col); }
};
vector<Group> Groups;
vector<string> ans, rect;
bool Found = false;
void divideWordByLength(const vector<string> &words)
{
for(const string &word : words)
{
if(word.length() >= Groups.size()) Groups.resize(word.length() + 1);
Groups[word.length()].addWord(word);
}
}
void DFS(size_t length, size_t height)
{
if(rect.size() == height){
Found = true;
ans = rect;
return;
}
const Group &group = Groups[length];
for(const string &word : group.WordSet)
{
if(!Found){
rect.push_back(word);
if(check(rect, height)){
DFS(length, height);
}
rect.pop_back();
}
}
}
bool check(const vector<string> &rect, const size_t height)
{
Group &group = Groups[height];
for(size_t col = 0; col < rect[0].size(); col++)
{
if(!group.partialContain(rect, col)) return false;
}
return true;
}
public:
vector<string> maxRectangle(vector<string>& words) {
divideWordByLength(words);
for(size_t length = Groups.size(); length > 1; length--)
{
for(size_t height = length; height > 1; height--)
{
if(!Groups[length - 1].empty() && !Groups[height - 1].empty()){
DFS(length - 1, height - 1);
if(!ans.empty()) return ans;
}
}
}
return ans;
}
};
本文深入探讨了WordRectangle算法,一种利用字典中的单词构造最大矩阵的问题。通过详细解释算法思路,包括字典分组、Trie树构建及深度优先搜索的应用,提供了清晰的代码实现与优化策略。

3万+

被折叠的 条评论
为什么被折叠?



