如何使下面的python程序对于大输入更有效地使用内存

问题描述

这个程序是要找出长度为 N 的字符串 S 中至少有 i 个不同字母的子串的个数,其中 1

def distinctChars (N,S):
    # Write your code here
    substrings = " ".join((S[i:j] for i in range(N) for j in range(i+1,N+1)))
    for i in range(1,27):
        if i==1:
            yield len(substrings.split(" "))
        else:
            yield len([item for item in substrings.split(" ") if len(set(item)) >= i])
    
 
N = int(input())
S = input()
 
out_ = distinctChars(N,S)
print (' '.join(map(str,out_)))

示例输入

N=4

A=aabc

输出

10 6 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

代码根据需要快速并且输出正确。但是不管怎么试,都超过了分配的250MB内存。

解决方法

我猜超出了内存限制,因为所有 substrings 都存储在一个变量中。您可以改为定义一个循环来仅预先计算代码中 len(set(item)) 的值:

def DistinctChars (N,S):
    
    all_U = []
    for i in range(N):
        D = set()
        for j in range(i,N):
            D.add(S[j])
            all_U.append(len(D))
    
    for i in range(1,27):
        yield sum( 1 for n in all_U if n>=i)

这种方法可以成倍地节省资源,因为所有子字符串都只被它们的唯一字符数替换。

附注。实际上可以构建一个更有效的算法,即立即计算具有给定数量的唯一字符的子字符串的数量。然后,最终答案对应于具有相同或更多唯一字符数的条目的累积总和:

def DistinctChars (N,S):
    
    all_N = [0]*27
    for i in range(N):
        D = set()
        for j in range(i,N):
            D.add(S[j])
            all_N[len(D)] += 1
    
    result = []
    s      =  0
    for i in range(26,-1):
        s += all_N[i]
        result.append(s)
    return reversed(result)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...