Python优化:在随机生成的1000个字母的字符串中查找最多出现的4个字母序列

Python优化:在随机生成的1000个字母的字符串中查找最多出现的4个字母序列,python,string,Python,String,我来这里是想寻求有关我的计划的帮助。 我意识到有一个程序存在的理由是在随机生成的x个字母较大的字符串上找到出现最多的四个字母字符串 例如,如果您知道'abcdeabcdef'中最常出现的四个字母的序列,那么很容易理解这是'abcd',因此程序将返回此值 不幸的是,我的程序运行非常慢,我的意思是,它需要119.7秒来分析所有的可能性,并且只显示1000个字母的字符串的结果 这是我的节目,现在: 随机导入 字符=['a'、'b'、'c'、'd'、'e'、'f'、'g'、'h'、'i'、'j'、'k'

我来这里是想寻求有关我的计划的帮助。 我意识到有一个程序存在的理由是在随机生成的x个字母较大的字符串上找到出现最多的四个字母字符串

例如,如果您知道
'abcdeabcdef'
中最常出现的四个字母的序列,那么很容易理解这是
'abcd'
,因此程序将返回此值

不幸的是,我的程序运行非常慢,我的意思是,它需要119.7秒来分析所有的可能性,并且只显示1000个字母的字符串的结果

这是我的节目,现在:

随机导入
字符=['a'、'b'、'c'、'd'、'e'、'f'、'g'、'h'、'i'、'j'、'k'、'l'、'm'、'n'、'o'、'p'、'q'、'r'、's'、't'、'u'、'v'、'w'、'x'、'y'、'z']
字符串=“”
对于范围(1000)内的:
string+=str(字符[random.randint(0,25)])
打印(字符串)
数字=[]
对于(0,26)范围内的
打印
对于范围(0,26)内的
对于范围(0,26)内的
对于范围(0,26)内的uu:
测试=字符[\uuuuu]+字符[\uuuuu]+字符[\uuuuu]+字符[\uuuuu]
打印('trying:',test,end='')
编号。追加(0)
对于范围内的i(长度(字符串)-3):
如果字符串[i:i+4]==测试:
数字[len(number)-1]+=1
打印(“>>已完成”)
_max=max(数字)
对于范围内的i(长度(编号)-1):
如果编号[i]==\u最大值:
j、 k,l,m=i,0,0,0
当j>25时:
j-=26
k+=1
当k>25时:
k-=26
l+=1
当l>25时:
l-=26
m+=1
结果=字符[m]+字符[l]+字符[k]+字符[j]
打印(str(结果),‘发生’,_max,‘次数’)

我认为有办法优化它,但在我的水平上,我真的不知道。也许结构本身不是最好的。希望您能帮助我:D

您只需在列表中循环一次,即可计算出4个字母的顺序。您当前正在循环
n*n*n*n
。您可以使用zip创建一个收集997个子字符串的四字母序列,然后使用计数器对其进行计数:

from collections import Counter
import random

chars = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']   
s = "".join([chars[random.randint(0, 25)] for _ in range(1000)])

it = zip(s, s[1:], s[2:], s[3:])
counts = Counter(it)
counts.most_common(1)
编辑:

.most_common(x)
返回
x
最常用字符串的列表<代码>计数。最常见的(1)返回单个项目列表,其中包含字母元组及其出现次数<代码>[(('a','b','c','d'),2)]。因此,要获得一个字符串,只需索引到其中并
join()


即使使用当前的方法迭代每个可能的4个字母组合,也可以通过保留字典而不是列表,并在尝试计数出现次数之前测试序列是否首先出现,从而大大提高速度:

counts = {}
for a in chars:
    for b in chars:
        for c in chars:
            for d in chars:
                test = a + b + c + d
                print('trying :',test, end = ' ')
                if test in s: # if it occurs at all
                    # then record how often it occurs
                    counts[test] = sum(1 for i in range(len(s)-4)
                                       if test == s[i:i+4])
多个循环可以替换为
itertools.permutations
,但这会提高可读性而不是性能:

length = 4
for sequence in itertools.permutations(chars, length):
    test = "".join(sequence)
    if test in s:
        counts[test] = sum(1 for i in range(len(s)-length) if test == s[i:i+length])
然后可以如下方式显示结果:

_max = max(counts.values())
for k, v in counts.items():
    if v == _max:
        print(k, "occurred", _max, "times")
如果字符串较短或与26**4个字符的长度相同,则遍历字符串比遍历每个组合要快得多:

length = 4
counts = {}
for i in range(len(s) - length):
    sequence = s[i:i+length]
    if sequence in counts:
        counts[sequence] += 1
    else:
        counts[sequence] = 1

这相当于

你熟悉滚动散列吗,还是?“在'abcdeabcdef'中,很容易理解为'abcd',因此程序将返回这个“嗯,那么'bcde'呢?它也存在两次。提示:你可以在字典中使用四个字母的子字符串作为键,将其映射到其频率。@abdusco否我要这样搜索:D@YuryTarabanko哦,是的,那是真的,是的,我会把钱还给你的two@Edhyjox我没有在pyInstaller中尝试过,但是集合是标准python发行版的一部分,所以我认为它应该没有问题。您也可以使用同样的技术将计数保存到dict中-使用
计数器
更不方便。好吧!非常感谢。我根本不知道如何使用它,我的意思是,如何得到一个对字母xD进行计数的字符串,我只是不懂xD
length = 4
counts = {}
for i in range(len(s) - length):
    sequence = s[i:i+length]
    if sequence in counts:
        counts[sequence] += 1
    else:
        counts[sequence] = 1