通过删除字母匹配到字典里最长单词

leetcode题号:524

题目

给定一个字符串和一个字符串字典,找到字典里面最长的字符串,该字符串可以通过删除给定字符串的某些字符来得到。如果答案不止一个,返回长度最长且字典顺序最小的字符串。如果答案不存在,则返回空字符串。

示例 1:

1
2
3
4
5
输入:
s = "abpcplea", d = ["ale","apple","monkey","plea"]
输出:
"apple"

示例 2:

1
2
3
4
5
输入:
s = "abpcplea", d = ["a","b","c"]
输出:
"a"

说明:

  • 所有输入的字符串只包含小写字母。
  • 字典的大小不会超过 1000。
  • 所有输入的字符串长度不会超过 1000。

临时解法

还是使用哈希表存储字典,然后逐个删除原字符串的某个字符,再递归。
简单的字符串还行,长字符串容易超时。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
public:
bool found = false;
string res;
void myfind(string s, unordered_map<string, int> &myhash){
if(s.size() > 0){
for(int i = 0; i < s.size(); i++){
auto ptr = myhash.find(s);
if(ptr != myhash.end()){
res = ptr->first.size() > res.size() ? ptr->first : res;
found = true;
}else{
string temp_str = s.substr(0, i) + s.substr(i + 1, s.size() - 1 - i);
myfind(temp_str, myhash);
}
}
}
}
string findLongestWord(string s, vector<string>& d) {
unordered_map<string, int> myhash;
sort(d.begin(), d.end());
for(int i = 0; i < d.size(); i++) myhash.insert(pair<string, int>(d[i], i));
myfind(s, myhash);
return res;
}
};

有两处做的不够好,一处是使用了递归,导致递归时的时间复杂度变为O(26^n).
第二处是字典序的处理上,虽然进行了排序,但在逐个删除字符寻找匹配时却不是按照字典序,所以字典序相当于没有处理。

下面的解法一是参考题解中的答案,有参考价值。

解法一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public:
bool found = false;
string res;
// 给原始字符串,看某个单词是否match
string mymatch(string s, string mydict){
int i, j;
for(i = 0, j = 0; i < s.size() && j < mydict.size(); ){
if(s[i] == mydict[j]) j++;
i++;
}
return j == mydict.size() ? mydict : "";
}
string findLongestWord(string s, vector<string>& d) {
string res;
for(auto m : d){
string temp = mymatch(s, m);
if(temp.size() > res.size()) res = temp;
else if(temp.size() == res.size()){
if(temp < res) res = temp;
}
}
return res;
}
};

优点一:自定义match函数,做删除字符的匹配,时间复杂度估计为 O(字典数组的大小 x min(字符串长度, 字典长度));

思考:leetcode将此题列为与最长前缀树相关的题目,是不是可以用最长前缀树解决此题呢?

0%