查找字符串的最长子序列 s,例如 "abccdde" 并给定字典 {"ab","add","aced"} 。上面示例的结果是“添加”
我在一次采访中被问到,我使用特里树给出了答案,最坏的情况是 O(n*m) ,n 是 s 的长度,m 是字典的长度。但我的平均成本应该很低。我没有通过面试,因为面试官认为我的解决方案不是最好的。有没有人有更好的主意?
查找字符串的最长子序列 s,例如 "abccdde" 并给定字典 {"ab","add","aced"} 。上面示例的结果是“添加”
我在一次采访中被问到,我使用特里树给出了答案,最坏的情况是 O(n*m) ,n 是 s 的长度,m 是字典的长度。但我的平均成本应该很低。我没有通过面试,因为面试官认为我的解决方案不是最好的。有没有人有更好的主意?
您可以创建一个图形,然后顶点就是您的字母表。对于字典中的每个单词,您将在图表中添加第一个字符,例如:
G[word[0]].add({word, 0})
然后,当您访问每个字母的文本时,您会访问该字母的 adyacency 列表。对于列表中的每个项目,您应该为该单词添加下一个字符。
用你的例子:
S = "abccdde", D = {"ab","add","aced"}
第一步:
G = {{'a', [{"ab", 0}, {"add", 0}, {"aced", 0}]}}
对于 S 中的每个字符
您访问该角色的列表
[{"ab", 0}, {"add", 0}, {"aced", 0}]
并更新您的图表
G = {{'b', [{"ab", 1}]}, {'d', ["add", 1]}, {'c', [{"aced", 1}]}}
您访问该角色的列表
[{"ab", 1}]
并更新您的图表
G = {{'d', ["add", 1]}, {'c', [{"aced", 1}]}}
当你完成“ab”时,你可以尝试改进你的答案。
您访问该角色的列表
[{"aced", 1}]
并更新您的图表
G = {{'d', ["add", 1]}, {'e', [{"aced", 2}]}}
该字符没有列表,然后您继续下一个字符
您访问该角色的列表
["add", 1]
并更新您的图表
G = {{'d', ["add", 2]}, {'e', [{"aced", 2}]}}
...
你可以使用这个方法
public static Boolean IsSubsequence(string ch, string item)
{
if (ch.Length < item.Length)
{
return false;
}
int indexItem = 0;
int indexCh = 0;
while (indexCh < ch.Length && indexItem< item.Length)
{
if (ch[indexCh] == item[indexItem])
{
indexItem++;
}
indexCh++;
}
return indexItem == item.Length;
}
它是 o(n) 方法您也可以从按单词长度对字典项目进行排序开始,所以第一个返回 true 的将是结果
我认为不可能只使用一个循环来减少算法所花费的时间,至少它需要两个循环我猜,这是我的方法:
public String lookFor(String inputWord, String[] dictionary) {
Arrays.sort(dictionary);
for (int index = dictionary.length - 1; index > 0; index--) {
if (isTheWordASubsequence(inputWord, dictionary[index]))
return dictionary[index];
}
return null;
}
private boolean isTheWordASubsequence(String inputWord,
String dictionaryWord) {
int spot = 0;
int offset = 0;
for (char item : dictionaryWord.toCharArray()) {
spot = (offset = inputWord.indexOf(item, spot)) >= spot ? offset : -1;
if (spot < 0)
return false;
}
return true;
}
安排您的字典数据结构,以便对于每个有效字母,您可以更深入地进入树(查看长一个字母的单词),并添加一个默认大小写(没有与此前缀匹配的字母)指向比当前深度(还有一个标志,表明您已经有一个词,以防万一结果是您的最佳选择)。
当您错过“asparag”后跟“r”时,如果有任何此类单词,您的字典会将您定向到“sparag”树,如果没有,则将您定向到“parag”。
对于每次失败,如果仍然没有匹配,您重复测试并递归到更短的单词;所以这仍然比 O(n) 更糟糕......尽管片刻的随意思考表明最坏的情况可能是 O(2n)。
为了加快速度,默认值可以是一个默认值列表,您可以从中选择与当前字母匹配的条目。所有条目将至少匹配长度为 0(当前字母无词开头)或 1(仅当前字母)的条目。
这是我的 Python 代码,用于时间复杂度为 O(N + L) 的解决方案,其中 N 是字符串中的字符数(对于“abccdde”,N = 7),L 是字典中的字符总数(对于 {"ab","add","aced"}),L = 9。基本上,它是线性时间复杂度。
def find_longest_word_in_string(string, words):
m = {}
for word in words:
m[word] = 0
for c in string:
for word in m.keys():
if len(word) == m[word]:
continue
else:
if word[m[word]] == c:
m[word] += 1
length = 0
for word in m.keys():
if m[word] == len(word) and m[word] > length:
res = word
length = m[word]
return res
if __name__ == '__main__':
s = "abccdde"
words = ["ab","add","aced"]
print find_longest_word_in_string(s, words)
运行它,返回“添加”