425. 单词方块

题目:

给定一个单词集合 (没有重复),找出其中所有的 单词方块 。

一个单词序列形成了一个有效的单词方块的意思是指从第 k 行和第 k 列 (0 ≤ k < max(行数, 列数)) 来看都是相同的字符串。

例如,单词序列 ["ball","area","lead","lady"] 形成了一个单词方块,因为每个单词从水平方向看和从竖直方向看都是相同的。

b a l l
a r e a
l e a d
l a d y
注意:

单词个数大于等于 1 且不超过 500。
所有的单词长度都相同。
单词长度大于等于 1 且不超过 5。
每个单词只包含小写英文字母 a-z。
 

示例 1:

输入:
["area","lead","wall","lady","ball"]

输出:
[
[ "wall",
"area",
"lead",
"lady"
],
[ "ball",
"area",
"lead",
"lady"
]
]

解释:
输出包含两个单词方块,输出的顺序不重要,只需要保证每个单词方块内的单词顺序正确即可。
 

示例 2:

输入:
["abat","baba","atan","atal"]

输出:
[
[ "baba",
"abat",
"baba",
"atan"
],
[ "baba",
"abat",
"baba",
"atal"
]
]

解释:
输出包含两个单词方块,输出的顺序不重要,只需要保证每个单词方块内的单词顺序正确即可。

 

解答:

开始直接暴力dfs妥妥的超时。正确做法是利用前缀特性,即

如果我们知道结果中第一个单词,那么下一个单词前缀我们是知道的。

比如有[ball],我们知道单词方块是 4X4,换句话说每个单词长度都为4,其次下个单词是a字母开头的。

假如我们找到一个a开头长度为4单词,变成[ball, area],那么第三个单词的前缀是le长度为4单词,依次类推。

 

所以要先计算不同前缀对应的单词有哪些。

方法1:trie树

方法2:map

 

我写的是用map的,用一个unordered_map<string,unordered_set<int>> mp。

mp[str]是一个int集合,其中每个int都是前缀为str的单词索引。

 

代码:

 1 class Solution {
 2 public:
 3     int limit;
 4     unordered_map<string,unordered_set<int>> mp;
 5     vector<vector<string>> wordSquares(vector<string>& words) {
 6         if(words.empty() or words[0].empty()){return {};}
 7         vector<vector<string>> res;
 8         limit=words[0].size();
 9         vector<int> cur;
10         for(int i=0;i<words.size();++i){
11             string prefix="";
12             for(int j=0;j<words[i].size();++j){
13                 prefix+=words[i][j];
14                 mp[prefix].insert(i);
15             }
16         }
17         for(int i=0;i<words.size();++i){
18             cur.emplace_back(i);
19             dfs(res,words,cur);
20             cur.pop_back();
21         }
22         return res;
23     }
24 
25     void dfs(vector<vector<string>>& res,vector<string>& words,vector<int>& cur){
26         // for(int x:cur){
27         //     cout<<words[x]<<endl;
28         // }cout<<"-----------------"<<endl;
29         if(cur.size()>=limit){//加入结果数组
30             vector<string> cur_res;
31             for(int i=0;i<cur.size();++i){
32                 cur_res.emplace_back(words[cur[i]]);
33             }
34             res.emplace_back(move(cur_res));
35             return;
36         }
37         string prefix="";//先算下一个单词需要满足的前缀
38         for(int j=0;j<cur.size();++j){
39             prefix+=words[cur[j]][cur.size()];
40         }
41         if(mp.count(prefix)){
42             for(int i:mp[prefix]){
43                 cur.push_back(i);
44                 dfs(res,words,cur);
45                 cur.pop_back();
46             }
47         }
48     }
49 };

 

posted @ 2020-03-06 19:04  NeoZy  阅读(301)  评论(0编辑  收藏  举报