Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/385.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
java.lang.OutOfMemoryError:查找长度为n的所有字符串的java堆空间_Java_Out Of Memory - Fatal编程技术网

java.lang.OutOfMemoryError:查找长度为n的所有字符串的java堆空间

java.lang.OutOfMemoryError:查找长度为n的所有字符串的java堆空间,java,out-of-memory,Java,Out Of Memory,我想用字母a、b和c生成所有可能的长度为n的字符串。。我得到这个错误java.lang.OutOfMemoryError:java堆空间。我的堆大小是512m。你能给我一些建议吗?你是在计算字符串还是在计算字符串 编辑:我从后面的评论中看到,您知道您正在谈论多少字符串: 如果你只是在计数,那是一种标准的排列闭合形式:26^n=26,升到n次方(假设你只使用从“a”到“z”的小写字母) 如果您确实试图枚举每个字符串,我强烈建议您确保不要保留对每个字符串的引用。如果您最终得到对这些字符串中的每一个的

我想用字母a、b和c生成所有可能的长度为n的字符串。。我得到这个错误
java.lang.OutOfMemoryError
:java堆空间。我的堆大小是512m。你能给我一些建议吗?

你是在计算字符串还是在计算字符串

编辑:我从后面的评论中看到,您知道您正在谈论多少字符串: 如果你只是在计数,那是一种标准的排列闭合形式:
26^n
=26,升到n次方(假设你只使用从“a”到“z”的小写字母)


如果您确实试图枚举每个字符串,我强烈建议您确保不要保留对每个
字符串的引用。如果您最终得到对这些字符串中的每一个的悬空引用,那么在大约六个字符之后,您的内存将耗尽。

当前正在计算的字符串数为

3^30 =                205 891 132 094 649
这是相当多的

知道每个字符串包含三个字节:

3^30 * 3 =            617 673 396 283 947
加上二维数组的32位或64位指针

3^30 * (3 + 4) =    1 441 237 924 662 540  // 32-bit Java VM
3^30 * (3 + 8) =    2 264 802 453 041 140  // 64-bit Java VM
那是

2 109 261 GB = 2059 TB     // 64-bit JVM
我想这就是问题所在


使用500 MB的限制,您可以求解以下等式:

  3^x * (3 + 8) = 524 288 000
            3^x = 47662545
              x = log(47662545) / log(3)
              x = 7 / 0.477121254719662
              x = 14.67

所以,如果我什么都没忘,你的测试应该适用于
n我在你的评论中提到的你有一个不同的问题。您希望找到所有长度为30且a-z不包含a-c的字符串。这是长度为30且为d-z的所有字符串的计数。计数为(26-3)^30

印刷品

71,094,348,791,151,363,024,389,554,286,420,996,798,449
There are 205,891,132,094,649 strings
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaab
aaaaaaaaaaaaaaaaaaaaaaaaaaaaac
aaaaaaaaaaaaaaaaaaaaaaaaaaaaba
aaaaaaaaaaaaaaaaaaaaaaaaaaaabb
aaaaaaaaaaaaaaaaaaaaaaaaaaaabc
aaaaaaaaaaaaaaaaaaaaaaaaaaaaca
aaaaaaaaaaaaaaaaaaaaaaaaaaaacb
aaaaaaaaaaaaaaaaaaaaaaaaaaaacc
aaaaaaaaaaaaaaaaaaaaaaaaaaabaa
... some numbers skipped ...
cccccccccccccccccccccccccccbcc
ccccccccccccccccccccccccccccaa
ccccccccccccccccccccccccccccab
ccccccccccccccccccccccccccccac
ccccccccccccccccccccccccccccba
ccccccccccccccccccccccccccccbb
ccccccccccccccccccccccccccccbc
ccccccccccccccccccccccccccccca
cccccccccccccccccccccccccccccb
cccccccccccccccccccccccccccccc

您可以将每个可能的字符串编码为数字,而不是记住每个字符串。在您的情况下,您可以使用
long

public static void main(String... args) {
    String letters = "abc";
    int len = 30;
    long combinations = (long) Math.pow(letters.length(), len);
    System.out.printf("There are %,d strings%n", combinations);
    for (long i = 0; i < 10; i++)
        System.out.println(fromLong(i, letters, len));
    System.out.println("... some numbers skipped ...");
    for (long i = combinations-10; i < combinations; i++)
        System.out.println(fromLong(i, letters, len));
}

public static String fromLong(long n, String letters, int len) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < len; i++) {
        sb.append(letters.charAt((int) (n % letters.length())));
        n /= letters.length();
    }
    return sb.reverse().toString();
}

这可以打印从0到3^30-1的所有可能字符串。您不需要存储所有编码的值,因为您知道所有可能的值都在一个连续的范围内。

不包含子字符串“ABC”的字符串计数可以通过动态编程解决

首先,让我们将长度为n的所有字符串的数量命名为
S(n)
。请注意,
S(n)
易于计算
S(n)=功率(字母表的大小,n)

让我们将包含长度为n的“ABC”的所有字符串的编号命名为
A(n)
,并将在第k个位置第一次出现“ABC”的所有字符串的编号命名为
A(n,k)

现在请注意:
A(n,k)=(S(k-1)-A(k-1))*S(n-k-3)
(由于k是出现“ABC”的第一个位置,这些字符串中的每一个都有一个子字符串,在该位置之前没有“ABC”,在第一个“ABC”之后有任何子字符串)

注意,
A(n)=[0..n-3]中k的和A(n,k)

现在我们可以计算
A(n)
从0开始计算
A(n)
的每个值

基本情况很简单,因为
A(n)=0表示n=0,1,2

A(3)=(S(0)-A(0))*S(0)=1
(即“ABC”)

等等

一旦你有了
A(n)
你就可以用公式
S(n)-A(n)
得到你要找的号码

伪Java伪代码:

public class Counter {


    public int count(int aSize, int n) {
        long[] a = new long[n+1]; // n + 1 elements since a[i] contains # of strings containing "ABC"
        a[0] = 0;
        a[1] = 0;
        a[2] = 0;


        for (int i = 3; i <= n; ++i){
            long sum = 0;
            for (int k = 0; k <= i-3; ++k) {
                sum += (pow(aSize, k) - a[k]) * pow(aSize, i - k - 3);
            }
            a[i] = sum;
        }
        return a[n];

    }

    public static void main(String... args) {
        int aSize = 3; //size of the alphabet
        int n = 30; // length of the strings

        //final result
        long result = pow(aSize, n) - count(aSize, n);


    }
}    
公共类计数器{
公共整数计数(整数aSize,整数n){
long[]a=new long[n+1];//n+1个元素,因为a[i]包含#个包含“ABC”的字符串
a[0]=0;
a[1]=0;
a[2]=0;

对于(int i=3;i)您尝试查找所有置换的长度是多少?为什么到处都使用BigInteger?您的数字有多大?最大值是3^30。备选值将非常有用。我想删除并查找不包含“ABC”的子字符串的计数。所以您要求的是(3**30)*30字节的存储空间。你知道这是多少吗?@HotLicks是的,我有。你有没有其他方法来处理我的代码以找到所有的置换。哇,它能工作吗?
main(String…args)
。我不知道我们可以用varargs作为主方法。很好。但是,+1。@Chris:没错。(我喜欢这个评论:D)@MartijnCourteaux这证明了你有多蠢?@DineshKukreja:我想你的评论证明了你有多笨。虽然这可能不是幽默?你为什么认为Chris的评论获得了3票赞成票?非常感谢。我不知道如何使用动态编程。谢谢你的帮助。@DineshKukreja没问题。小心溢出。这是很好的obably应该是long而不是int(甚至是BigDecimal)。我将编辑答案。
There are 205,891,132,094,649 strings
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaab
aaaaaaaaaaaaaaaaaaaaaaaaaaaaac
aaaaaaaaaaaaaaaaaaaaaaaaaaaaba
aaaaaaaaaaaaaaaaaaaaaaaaaaaabb
aaaaaaaaaaaaaaaaaaaaaaaaaaaabc
aaaaaaaaaaaaaaaaaaaaaaaaaaaaca
aaaaaaaaaaaaaaaaaaaaaaaaaaaacb
aaaaaaaaaaaaaaaaaaaaaaaaaaaacc
aaaaaaaaaaaaaaaaaaaaaaaaaaabaa
... some numbers skipped ...
cccccccccccccccccccccccccccbcc
ccccccccccccccccccccccccccccaa
ccccccccccccccccccccccccccccab
ccccccccccccccccccccccccccccac
ccccccccccccccccccccccccccccba
ccccccccccccccccccccccccccccbb
ccccccccccccccccccccccccccccbc
ccccccccccccccccccccccccccccca
cccccccccccccccccccccccccccccb
cccccccccccccccccccccccccccccc
public class Counter {


    public int count(int aSize, int n) {
        long[] a = new long[n+1]; // n + 1 elements since a[i] contains # of strings containing "ABC"
        a[0] = 0;
        a[1] = 0;
        a[2] = 0;


        for (int i = 3; i <= n; ++i){
            long sum = 0;
            for (int k = 0; k <= i-3; ++k) {
                sum += (pow(aSize, k) - a[k]) * pow(aSize, i - k - 3);
            }
            a[i] = sum;
        }
        return a[n];

    }

    public static void main(String... args) {
        int aSize = 3; //size of the alphabet
        int n = 30; // length of the strings

        //final result
        long result = pow(aSize, n) - count(aSize, n);


    }
}