我指的是算法问题:
http://www.ardendertat.com/2012/06/15/programming-interview-questions-28-longest-compound-word/
给定一个排序的单词列表,找到最长的复合单词 通过连接列表中的单词构建的列表。对于 例如,如果输入列表是:['cat','cats','catsdogcats', 'catxdogcatsrat','dog','dogcatsdog','hippopotamuses','rat', 'ratcat','ratcatdog','ratcatdogcat']。然后是最长的复合词 是'ratcatdogcat'有12个字母。注意最长的个体 单词是'catxdogcatsrat'和'hippopotamuses',有14个字母,但是 他们并没有完全用其他词语构建。前者有一个额外的 'x'字母,后者是一个单独的单词本身不是一个复合词 字。
我按如下方式实现了算法:
从输入列表中的所有单词构造一个Trie。每个节点代表一个字符,单词的结尾通过设置isTerminal=true
。
现在我有另一种方法来检查每个输入字,以找出它所构成的组件数量(比如复合长度)。例如,在上面的示例中,ratcatdogcat
由输入列表rat
,cat
,dog
和cat
中的单个词组成。我这样做是通过递归地解析输入单词的有效前缀并找到单词其余部分的复合长度,即解析rat
并获得catdogcat
的复合长度。如果休息的复合长度为zero
,则表示休息不是有效的构造,我尝试下一个前缀ratcat
并递归dogcat
。
伪代码如下所示:
Node {
Character ch
Map<Character, Node> children
boolean isTerminal
}
int getCompoundLength(word) {
if (dpTable.contains(word))
return dpTable.get(word)
dpTable.put(word, 0) // memoize word to compound length
Node current = root;
for (i=0 to word.length) {
ch = word[i]
if (!current.children.contains(ch)) // invalid character
return 0;
current = current.children.get(ch)
if (!current.isTerminal) // not a valid prefix yet
continue
lenRest = getCompoundLength(word.substring(i+1));
if (lenRest != 0) { // rest of the string is valid
dpTable.put(word, lenRest+1)
return lenRest + 1
}
}
// Could not split the word into multiple components.
// Check if word is a valid word at least.
if (current.isTerminal) {
dpTable.put(word, 1)
return 1;
}
我知道构造trie需要O(W),其中W是输入字的总数。但我不清楚如何计算getCompoundLength
方法的运行时间。感谢任何帮助。
答案 0 :(得分:1)
你的理解是错误的。在单词中插入一个单词具有该单词长度的运行时间,因此构建该单词的时间为O(W*s)
,其中s
是该单词的平均大小。
查找特里结尾的单词是最差的O(s)
,其中s
是该单词的长度。
至于你的getCompoundLength
方法,你需要提出最悲观的可能输入。请考虑以下示例:
a
aa
aaa
aaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab
最后一个字不是复合词。但是你刚刚想出那个指数回溯问题......
(真实世界的正则表达式实现在黑桃中有这个问题。它们在大多数字符串上都能正常工作,但是有一些病理输入会让它们发出哔哔声。)