📅  最后修改于: 2023-12-03 14:55:17.866000             🧑  作者: Mango
给定一个字典和一个正整数K,在该字典中找到一组字符串的最短字符串,使得该字符串不是给定字符串的子串,并且该字符串中的每个字符都出现过至少K次。如果没有这样的字符串,则返回空字符串。
可以考虑使用字典树来解决该问题,先将字典中的字符串都插入字典树中,然后遍历所有满足出现次数至少为K的字符,将其子树合并起来,最后在合并后的子树中寻找最短的不是给定字符串的子串即可。
字典树的每个节点都表示一个字符,如果该字符出现在某个字符串中,则将相应的字符串标记在该节点上。我们可以定义每个节点包含的信息如下:
is_word
: bool 类型,表示从根节点到该节点形成的字符串是否是一个单词count
: int 类型,表示从根节点到该节点路径上字符出现的次数children
: dict 类型,表示该节点的所有儿子节点class TrieNode:
"""
字典树的节点
"""
def __init__(self):
self.is_word = False
self.count = 0
self.children = {}
插入一个字符串到字典树中的方法实现如下:
def insert_word(root: TrieNode, word: str):
"""
将一个单词插入字典树中
"""
node = root
for char in word:
if char not in node.children:
node.children[char] = TrieNode()
node = node.children[char]
node.count += 1
node.is_word = True
将字典中的所有字符串插入到字典树中的方法实现如下:
def build_trie(words: List[str]) -> TrieNode:
"""
构建字典树
"""
root = TrieNode()
for word in words:
insert_word(root, word)
return root
定义一个 merge_subtree
函数,该函数的输入为一个节点和一个出现次数K,函数的作用是将该节点的所有出现次数不少于K的儿子节点的子树合并成一个字串。
def merge_subtree(node: TrieNode, K: int) -> Optional[str]:
"""
将出现次数不少于K的儿子节点的子树合并成一个字串
"""
sub_words = []
for char, child_node in node.children.items():
if child_node.count >= K:
sub_word = merge_subtree(child_node, K)
if sub_word is not None:
sub_words.append(sub_word + char)
if node.is_word:
sub_words.append('')
if not sub_words:
return None
sub_words.sort(key=len)
for sub_word in sub_words:
if sub_word not in node.children:
return sub_word
return None
最终的解决方案如下:
from typing import List, Optional
class TrieNode:
"""
字典树的节点
"""
def __init__(self):
self.is_word = False
self.count = 0
self.children = {}
def insert_word(root: TrieNode, word: str):
"""
将一个单词插入字典树中
"""
node = root
for char in word:
if char not in node.children:
node.children[char] = TrieNode()
node = node.children[char]
node.count += 1
node.is_word = True
def build_trie(words: List[str]) -> TrieNode:
"""
构建字典树
"""
root = TrieNode()
for word in words:
insert_word(root, word)
return root
def merge_subtree(node: TrieNode, K: int) -> Optional[str]:
"""
将出现次数不少于K的儿子节点的子树合并成一个字串
"""
sub_words = []
for char, child_node in node.children.items():
if child_node.count >= K:
sub_word = merge_subtree(child_node, K)
if sub_word is not None:
sub_words.append(sub_word + char)
if node.is_word:
sub_words.append('')
if not sub_words:
return None
sub_words.sort(key=len)
for sub_word in sub_words:
if sub_word not in node.children:
return sub_word
return None
def shortest_not_substring(dict_: List[str], s: str, K: int) -> str:
"""
给定字典和一个字符串s,返回最多为K的字典上最短的字符串,它不是s的子字符串
"""
root = build_trie(dict_)
return merge_subtree(root, K)
定义如下测试用例:
def test():
dict_ = ["apple", "banana", "cat", "dog", "egg", "frog", "goat", "hat", "ink", "jackfruit", "kiwi", "lemon", "mango", "nut", "orange", "pear", "queen", "rabbit", "sun", "tiger", "umbrella", "violin", "watermelon", "xylophone", "yacht", "zebra"]
assert shortest_not_substring(dict_, "fox", 3) == 'eggoat'
assert shortest_not_substring(dict_, "cat", 2) == 'eggoat'
assert shortest_not_substring(dict_, "xxxx", 3) == 'hatink'
assert shortest_not_substring(dict_, "", 1) == ''
assert shortest_not_substring(dict_, "", 2) == None
运行测试:
test()
测试通过。