搜索子字符串时出现Python内存错误

时间:2015-11-21 07:08:38

标签: python memory

我正在尝试查找非常大的字符串的子字符串并导致内存错误:

代码:

def substr(string):
    le = []
    st = list(string)
    for s in xrange(len(string)+1):
        for s1 in xrange(len(string)+1):
            le.append(''.join(st[s:s1]))

    cou = Counter(le)
    cou_val = cou.keys()
    cou_val.remove('')
    return le, cou_val

我收到错误,因为ile" solution.py",第31行,在substr     le.append(''。加入(ST [S:S1])) 的MemoryError

如何解决这个问题?

3 个答案:

答案 0 :(得分:1)

<强>答案

我注意到您的代码按特定顺序打印了字符串的所有可能子字符串。我建议不要将所有这些存储在数组中,而是使用代码返回所需的子字符串。我用'非常长的字符串'测试了下面的子程序,并且它总是返回相同的值,就像从数组中获取索引值一样。

    string = 'a very long string'
    def substr2(string,i):
        return string[i//(len(string)+1):i%(len(string)+1)]

    print(substr2(string,10))

<强>解决方案

为for循环(s,s1)命令参数的方式与数字系统的工作方式类似。 s1递增1直到达到给定值,然后它重置为0并且s递增1,重复循环。这可以用十进制表示(例如01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16等)。

i // n div运算符返回i / n的整数值。 (例如14 // 10 = 1)。 i%n mod运算符返回i / n的余数值。 (例如14%10是4)。

因此,如果我们将i增加1并将(s,s1)定义为[i // 10,i%10],我们将得到:

[0,0],[0,1],[0,2],[0,3],[0,4],[0,5],[0,6],[0,7] ,[0,8],[0,9],[1,0],[1,1],[1,2]等。

我们可以利用这些来产生与数组相同的答案。

PS。我的第一个答案。希望这有帮助!

答案 1 :(得分:0)

你的内存似乎已经不多了。当string太大时,您发布的代码似乎将其一遍又一遍地复制到le列表中。正如@ Rikka的链接所示,buffer/memoryview可能对您有用,但我从未使用它。

作为解决方案/代码的变通方法,我建议不要将每个子字符串存储在le中,而是将索引存储为元组。另外,我不认为st列表是必需的(不确定如果你的方式加快它)所以结果将是(代码未测试):

def substr(string):
    le = []

    for s in xrange(len(string)+1):
        for s1 in xrange(len(string)+1):
            # Skip empty strings
            if s!=s1:
                le.append((s, s1))

    cou = Counter(le)
    cou_val = cou.keys()
    cou_val.remove('')
    return le, cou_val

现在,您可以使用substr的示例是(代码未经过测试):

myString = "very long string here"
matchString = "here"
matchPos = False
indexes, count = substr(myString)

# Get all the substrings without storing them simultaneously in memory
for i in indexes:
    # construct substring and compare
    if myString[i[0],i[1]]==matchString:
        matchPos = i
        break

在上面之后,您将第一次出现的“here”的开始和结束位置放入您的大字符串中。我不确定你试图实现什么,但是可以很容易地修改它以查找所有出现次数,计数匹配等 - 我只是将其作为示例发布。我也不确定为什么Counter在那里......

这种方法不应该出现内存错误,但是,它是内存和CPU之间的权衡,我希望它在运行时有点慢,因为每次使用indexes时都必须重新构建每个子串。

希望有所帮助

答案 2 :(得分:-1)

解决方案:           内存中的错误总是由超出范围引起。切片技术也有一些规则。           当步骤为正时,就像1一样,第一个索引必须大于第二个。而相反,当为负数时,如-1,索引的数量比第二个短,但实际上更大一个。( - 1> -2)           所以在你的程序中,当step为1时,索引s大于s1,所以你访问了一个你没有申请它的地方。你知道,那是MemoryError !! !