Python 给定的字符串列表只返回任何其他字符串中不包含的字符串

Python 给定的字符串列表只返回任何其他字符串中不包含的字符串,python,string,list,search,set,Python,String,List,Search,Set,我正试图找到一种计算友好的方法来执行以下操作: 给定字符串列表=['many'、'man'、'cat'、'caterpillar'、'pid'、'pi'、'pill'] returnsublist=['many'、'caterpillar'、'pillow'],即不包含在任何其他字符串中的字符串列表 最简单的解决方案是迭代元素并检查每个元素是否包含在另一个元素中,复杂度为O(n^2)(即使我考虑过一些小优化,比如按长度排序字符串,但这会增加排序的复杂度),但我认为这太贵了 我还考虑了实现一个tr

我正试图找到一种计算友好的方法来执行以下操作:

给定
字符串列表=['many'、'man'、'cat'、'caterpillar'、'pid'、'pi'、'pill']

return
sublist=['many'、'caterpillar'、'pillow']
,即不包含在任何其他字符串中的字符串列表

最简单的解决方案是迭代元素并检查每个元素是否包含在另一个元素中,复杂度为O(n^2)(即使我考虑过一些小优化,比如按长度排序字符串,但这会增加排序的复杂度),但我认为这太贵了

我还考虑了实现一个trie,然后将列表中的每个元素用作一个haystack,然后只保留一个haystack中包含的字符串(字符串本身)


我想我遗漏了比我所知道的更多的内容,所以我正在寻找建议。考虑到您的列表中没有重复项,以下建议应该有效(如果有,问题必须澄清它们会发生什么,并且代码可以调整):

输出:

print(result):

['many', 'caterpillar', 'pillow']

我已经实现了以下方法(但在接受任何答案之前,我渴望看到其他方法):

因此,在我们的案例中:

result = filter_matches(list_of_strings)
它使用包,包实现了用于字符串搜索的Aho-Corasick算法


与@IoaTzimas answers相比,它大大减少了计算时间:我在40k列表上对这两个问题进行了回溯测试,结果从大约330秒增加到不到一秒

您的列表中是否有重复项?@IoaTzimas nope,已经独一无二了!嗨,谢谢你的回答!我想将我的测试结果与你的测试结果进行对比,并根据这些结果选择最好的:)
import ahocorasick

def make_automation(list_of_tokens):
    A = ahocorasick.Automaton()
    for idx, key in enumerate(list_of_tokens):
        A.add_word(key, (idx, key))
    A.make_automaton()
    return A

def search_list_aho_corasick(txt_to_search, ahocorasick_automaton):
    match = []
    for end_index, (insert_order, original_value) in ahocorasick_automaton.iter(txt_to_search):
        start_index = end_index - len(original_value) + 1
        if original_value == txt_to_search:
            continue
        else:
            match.append(original_value) 
        assert txt_to_search[start_index:start_index + len(original_value)] == original_value
    return match

def filter_matches(list_of_matches):
    if len(list_of_matches) == 0:
        return list_of_matches
    else:
        aut = make_automation(list_of_matches)
        contained = []
        contained_result = list(map(lambda x: search_list_aho_corasick(x, aut), list_of_matches))
        return list(set(list_of_matches) - set(flatten_list(contained_result)))
result = filter_matches(list_of_strings)