Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 高效地生成字符串的所有可能子字符串的列表_Python_C++_C_String_List - Fatal编程技术网

Python 高效地生成字符串的所有可能子字符串的列表

Python 高效地生成字符串的所有可能子字符串的列表,python,c++,c,string,list,Python,C++,C,String,List,我想编写一个函数,根据子字符串的最小和最大长度,高效地返回字符串中所有可能的子字符串的列表。(字符串仅包含大写字母。) 例如,对于字符串“ThisisString”,对于最小长度=3和最大长度=4,它应该返回: ['THI', 'THIS', 'HIS', 'HISI', 'ISI', 'ISIS', 'SIS', 'SISA', 'ISA', 'ISAS', 'SAS', 'SAST', 'AST', 'ASTR', 'STR', 'STRI', 'TRI', 'TRIN', 'RIN',

我想编写一个函数,根据子字符串的最小和最大长度,高效地返回字符串中所有可能的子字符串的列表。(字符串仅包含大写字母。)

例如,对于字符串
“ThisisString”
,对于
最小长度=3
最大长度=4
,它应该返回:

['THI', 'THIS', 'HIS', 'HISI', 'ISI', 'ISIS', 'SIS', 'SISA', 'ISA',
 'ISAS', 'SAS', 'SAST', 'AST', 'ASTR', 'STR', 'STRI', 'TRI', 'TRIN',
 'RIN', 'RING', 'ING']
我正在寻找一种比当前解决方案快得多的解决方案:

import cProfile

random_english_text = \
    'AHOUSEISABUILDINGTHATISMADEFORPEOPLETOLIVEINITISAPERMANENTBUILDINGTHATISMEANTTOSTAYSTANDINGITISNOTEASILYPACKEDU' \
    'PANDCARRIEDAWAYLIKEATENTORMOVEDLIKEACARAVANIFPEOPLELIVEINTHESAMEHOUSEFORMORETHANASHORTSTAYTHENTHEYCALLITTHEIRHO' \
    'MEBEINGWITHOUTAHOMEISCALLEDHOMELESSNESSHOUSESCOMEINMANYDIFFERENTSHAPESANDSIZESTHEYMAYBEASSMALLASJUSTONEROOMORTH' \
    'EYMAYHAVEHUNDREDSOFROOMSTHEYALSOAREMADEMANYDIFFERENTSHAPESANDMAYHAVEJUSTONELEVELORSEVERALDIFFERENTLEVELSAHOUSEI' \
    'SSOMETIMESJOINEDTOOTHERHOUSESATTHESIDESTOMAKEATERRACEORROWHOUSEACONNECTEDROWOFHOUSES'

def assemble_substrings(textstring, length_min, length_max):
    str_len = len(textstring)
    subStringList = []
    idx = 0
    while idx <= str_len - length_min:
        max_depth = min(length_max, str_len - idx)
        for i in list(range(length_min, max_depth + 1)):
            subString = textstring[idx:idx + i]
            subStringList.append(subString)
        idx += 1
    return subStringList


pr = cProfile.Profile()
pr.enable()

for i in range(0, 1000):
    list_of_substrings = assemble_substrings(textstring=random_english_text, length_min=4, length_max=10)

pr.disable()
pr.print_stats(sort='cumtime')
导入cProfile
随机英文文本=\
“适用于居住的建筑物是永久性的建筑物,且不可随意堆放”\
“如果人们居住在同一所房子里,而不是居住在他们称之为他们自己的房子里,他们会像吃的或吃的一样被带走”\
“我没有所谓的房子,但有许多不同的形状和大小,它们可能只是一个小房间”\
“他们可能有上百个房间需要不同的形状,可能只有一个或几个不同的楼层”\
“SSO有时会连接到另一个位于侧气孔的房间或与房屋相连的房间”
def集合子字符串(文本字符串、最小长度、最大长度):
str_len=len(文本字符串)
子字符串列表=[]
idx=0

虽然idx为什么不简单地使用2个范围的列表理解和字符串切片

t = "SOMETEXT"

print(t)

minl = 3
maxl = 8

parts = [t[i:i+j] for i in range(len(t)-minl) for j in range(minl,maxl+1)]

print(parts)
输出:

['SOM', 'SOME', 'SOMET', 'SOMETE', 'SOMETEX', 'SOMETEXT', 'OME', 'OMET', 'OMETE', 'OMETEX', 
 'OMETEXT', 'OMETEXT', 'MET', 'METE', 'METEX', 'METEXT', 'METEXT', 'METEXT', 'ETE', 'ETEX', 
 'ETEXT', 'ETEXT', 'ETEXT', 'ETEXT', 'TEX', 'TEXT', 'TEXT', 'TEXT', 'TEXT', 'TEXT']
['SOM', 'SOME', 'SOMET', 'SOMETE', 'SOMETEX', 'SOMETEXT', 'OME', 'OMET', 'OMETE', 'OMETEX', 
 'OMETEXT', 'MET', 'METE', 'METEX', 'METEXT', 'ETE', 'ETEX', 'ETEXT', 'TEX', 'TEXT']
['THI', 'HIS', 'ISI', 'SIS', 'ISA', 'SAS', 'AST', 'STR', 'TRI', 'RIN', 'ING', 'THIS', 'HISI', 'ISIS', 'SISA', 'ISAS', 'SAST', 'ASTR', 'STRI', 'TRIN', 'RING']
如果顺序不重要,您可以使用集合删除重复项-否则为顺序存储创建唯一列表:

nodupes = [] 
k = set() 
for l in parts:
    if l in k:
        pass
    else:
        nodupes.append(l)
        k.add(l)

print(nodupes)   
输出:

['SOM', 'SOME', 'SOMET', 'SOMETE', 'SOMETEX', 'SOMETEXT', 'OME', 'OMET', 'OMETE', 'OMETEX', 
 'OMETEXT', 'OMETEXT', 'MET', 'METE', 'METEX', 'METEXT', 'METEXT', 'METEXT', 'ETE', 'ETEX', 
 'ETEXT', 'ETEXT', 'ETEXT', 'ETEXT', 'TEX', 'TEXT', 'TEXT', 'TEXT', 'TEXT', 'TEXT']
['SOM', 'SOME', 'SOMET', 'SOMETE', 'SOMETEX', 'SOMETEXT', 'OME', 'OMET', 'OMETE', 'OMETEX', 
 'OMETEXT', 'MET', 'METE', 'METEX', 'METEXT', 'ETE', 'ETEX', 'ETEXT', 'TEX', 'TEXT']
['THI', 'HIS', 'ISI', 'SIS', 'ISA', 'SAS', 'AST', 'STR', 'TRI', 'RIN', 'ING', 'THIS', 'HISI', 'ISIS', 'SISA', 'ISAS', 'SAST', 'ASTR', 'STRI', 'TRIN', 'RING']

定时:

def doit(t,minl,maxl):
    parts = [t[i:i+j] for i in range(len(t)-minl) for j in range(minl,maxl+1)]
    return parts

pr = cProfile.Profile()
pr.enable()

for i in range(0, 1000):
    list_of_substrings = doit(random_english_text, 4, 10)

pr.disable()
pr.print_stats(sort='cumtime')

3001函数调用只需0.597秒
排序人:累计时间
ncalls tottime percall cumtime percall文件名:lineno(函数)
1000 0.001 0.000 0.597 0.001主管道py:10(doit)
1000 0.596 0.001 0.596 0.001 main.py:11()
1000 0.000 0.000 0.000 0.000{内置方法内置.len}
1 0.000 0.000 0.000 0.000{方法'disable'的''lsprof.Profiler'对象}

您的给出:
4181001函数调用只需1.614秒

我不确定它实际有多快(阅读:需要进一步研究),但对我来说,它听起来像是正则表达式的任务(
re
模块),我会按照以下方式执行:

import re
minlen = 3
maxlen = 4
s = 'THISISASTRING'
out = []
for i in range(minlen,maxlen+1):
    p = re.compile('(?=(.{'+str(i)+'}))',re.DOTALL)
    out = out+p.findall(s)
print(out)
输出:

['SOM', 'SOME', 'SOMET', 'SOMETE', 'SOMETEX', 'SOMETEXT', 'OME', 'OMET', 'OMETE', 'OMETEX', 
 'OMETEXT', 'OMETEXT', 'MET', 'METE', 'METEX', 'METEXT', 'METEXT', 'METEXT', 'ETE', 'ETEX', 
 'ETEXT', 'ETEXT', 'ETEXT', 'ETEXT', 'TEX', 'TEXT', 'TEXT', 'TEXT', 'TEXT', 'TEXT']
['SOM', 'SOME', 'SOMET', 'SOMETE', 'SOMETEX', 'SOMETEXT', 'OME', 'OMET', 'OMETE', 'OMETEX', 
 'OMETEXT', 'MET', 'METE', 'METEX', 'METEXT', 'ETE', 'ETEX', 'ETEXT', 'TEX', 'TEXT']
['THI', 'HIS', 'ISI', 'SIS', 'ISA', 'SAS', 'AST', 'STR', 'TRI', 'RIN', 'ING', 'THIS', 'HISI', 'ISIS', 'SISA', 'ISAS', 'SAST', 'ASTR', 'STRI', 'TRIN', 'RING']

我用bernie的回答让
findall
以重叠的方式工作。我知道这个特殊的零长度断言可以利用可变长度模式,但是当我使用
re.findall('(?=(..3,4})),'THISISASTRING')
时,它产生了
['this','HISI','ISIS','SISA','ISAS','SAST','ASTR','STRI TRIN','RING ING']
,这不是期望的输出。因此,我为re
解决方案提供了混合
,每个循环都对应特定长度的字符串。在这里,我必须承认,我在
re
方面做得不够好,无法使它以单通方式工作(仅
re
,没有
for
),但是,也许其他用户能够完成它?

您可以映射
”。join()
到压缩字符串:

def func(s, min_l, max_l):
    return [subl for i in range(min_l, max_l + 1)
                 for subl in map(''.join, zip(*[s[i:] for i in range(i)]))]
轮廓: 输出:
ncalls tottime percall cumtime percall文件名:lineno(函数)
1000 0.002 0.000 0.772 0.001无标题。py:3(func)
7000 0.014 0.000 0.014 0.000无标题。py:4()
1 0.000 0.000 0.000 0.000{方法'disable'的''lsprof.Profiler'对象}

您想用它做什么?可能有一个比包含所有选项的列表更好的数据结构。此外,我认为您有一个边缘情况的错误,当循环处于字符串的最后一个长度时,它仍然会为每个允许的长度添加字符串。我认为字符串的结尾需要作为特例处理。对于结果列表(或其他数据结构)中的所有项,我希望能够:1。检查它们是否包含在另一个列表(或其他数据结构)2中。迭代所有元素并将它们用作访问字典的键。您的问题提醒了我另一个问题的一部分,尽管我记不清具体是哪个问题。可能吧?为什么要使用
列表(范围(…)
?似乎没有必要调用
list()
。非常感谢您的回答!不用说,你的回答比我的要优雅得多关于速度,你的解决方案大约比我的快3倍,这已经很好了,但如果它能快很多,那就更好了:)Thx对于你的答案,刚刚检查过,你的解决方案大约比我的快3倍。不过,我还是希望能有更大幅度的加速。:)