一种选择是将所有有效的英语单词存储在 trie 中。完成此操作后,您可以开始按照字符串中的字母从根向下遍历 trie。每当您找到标记为单词的节点时,您有两种选择:
- 此时中断输入,或
- 继续扩展这个词。
一旦您将输入分解为一组完全合法且没有剩余字符的单词,您就可以声称您找到了匹配项。由于在每个字母处,您要么有一个强制选项(要么您正在构建一个无效的单词并且应该停止 - 或者 - 您可以继续扩展单词)或两个选项(拆分或继续),因此您可以实现此功能使用穷举递归:
PartitionWords(lettersLeft, wordSoFar, wordBreaks, trieNode):
// If you walked off the trie, this path fails.
if trieNode is null, return.
// If this trie node is a word, consider what happens if you split
// the word here.
if trieNode.isWord:
// If there is no input left, you're done and have a partition.
if lettersLeft is empty, output wordBreaks + wordSoFar and return
// Otherwise, try splitting here.
PartitinWords(lettersLeft, "", wordBreaks + wordSoFar, trie root)
// Otherwise, consume the next letter and continue:
PartitionWords(lettersLeft.substring(1), wordSoFar + lettersLeft[0],
wordBreaks, trieNode.child[lettersLeft[0])
在最坏的情况下,这将列出字符串的所有分区,这些分区不能成指数增长。但是,只有当您可以以多种方式对字符串进行分区时才会发生这种情况,这些方式都以有效的英语单词开头,并且在实践中不太可能发生。但是,如果字符串有很多分区,我们可能会花费大量时间来查找它们。例如,考虑字符串“dotherdo”。我们可以通过多种方式拆分:
do the redo
do the red o
doth ere do
dot here do
dot he red o
dot he redo
为避免这种情况,您可能希望限制您报告的答案数量,可能是两个或三个。
由于我们在离开 trie 时切断了递归,所以如果我们尝试拆分时不会使字符串的其余部分保持有效,我们将很快检测到这一点。
希望这会有所帮助!