给定一系列字符,生成集合的所有字符串?

时间:2018-02-18 06:56:54

标签: java security

我的计算机安全课程需要帮助;在程序中我需要生成一个字符串的所有可能组合给定一组默认字符(字母,数字和一些特殊字符)。考虑到可能的长度为1到10个字符,我无法弄清楚如何正确地循环它们的方法。我能够创建一个简单的嵌套循环,适用于2位数,但我认为必须有一个更好的方法将其缩放到10个字符,并不需要复制粘贴循环再次lol。下面的第一个代码块是我对10位数的尝试,下面的代码是我2位数的尝试。任何帮助,即使在理解如何解决问题时也会非常感谢,谢谢。

String SALTCHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_$#-~";
    for(int i =1;i<11;i++) {
        String initialPW = StringUtils.repeat("a", i);
        StringBuilder potentialPW = new StringBuilder(initialPW);
        System.out.println("initial ps is "+initialPW);
        for (int j=0;j<67;j++) {

            String letterSwap = Character.toString(SALTCHARS.charAt(j));
            System.out.println("The swap letter is "+letterSwap);
            potentialPW.setCharAt(i-1, SALTCHARS.charAt(j));
            String saltStr = potentialPW.toString();
            System.out.println("The final pw guess is "+ saltStr); 
            for (int k = 0;k<i;k++) {
                potentialPW.setCharAt(k, SALTCHARS.charAt(j));
                saltStr = potentialPW.toString();
                System.out.println("The final pw guess is "+ saltStr); 
            }
        } 
    } 

这是我对这个概念的尝试,但有2个字符

String[] possiblePasswords = new String[676];
    int position = 0;
    for (int i = 97;i<123;i++) {
        for (int j = 97;j<123;j++) {
            String firstLetter = Character.toString((char) i);
            String secondLetter = Character.toString((char) j);
            //System.out.println("Test for: "+ firstLetter+secondLetter);
            possiblePasswords[position] = firstLetter + secondLetter;
            position++;
        }
    }

2 个答案:

答案 0 :(得分:2)

您需要使用回溯来生成给定长度的所有字符组合。如果生成的字符串的长度未修复,则需要使用递归,否则您将需要编写那么多嵌套循环。我编写了一个简单的C ++程序,它也是如此。但是,长度[1,10]会有很多可能的组合,并且创建所有这些组合会导致我的系统堆栈溢出(因为我正在使用递归)。但是你可以浏览代码并理解这样做的基本思路。如果你想执行这个代码来检查它,我建议你将hi的值更改为低(2-3可能)或将域大小缩小到较小的字符数,否则会导致堆栈溢出。 (hi表示所生成的字符串的期望上限)。

    #include<bits/stdc++.h>
using namespace std;
void create(int i,string domain,vector<bool>& included,string str,int len)
{
    if(i==(len))
    {
        cout<<str<<endl;
        return;
    }
    for(int j=0;j<domain.length();j++)
    {
        if(included[j]==1)
        continue;
        else
        {
            included[j]=1;
            str+=domain[j];
            create(i+1,domain,included,str,len);
            included[j]=0;
            str.pop_back();
        }
    }
}
int main()
{
    string domain = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_$#-~";
    int lo=1;
    int hi=10;
    for(int i=lo;i<=hi;i++)
    {
        int len=i;
        string str;
        vector<bool> included(domain.length(),0);
        create(0,domain,included,str,len);
    }
   return 0;
}

答案 1 :(得分:1)

嗯......有意思?

我想我可能有一个可怕的想法。

为简单起见,我将使用两个有效字符AB。 然后,假设我们想要为长度为2的字符串生成这两个字符的所有可能序列:

Array of all possible 2 length strings

我们可以使用二维数组表示所有可能的2个长度字符串... 然后,说我们想要找到所有可能的3个长度字符串...... 3D array of all possible 3 length strings

然后,我们可以通过迭代3D数组的每个元素,获得AB的所有可能组合,以获得长度为3的字符串。我们知道有8种可能的结果(2 ^ 3),实际上有8个“立方体”,即AAA, AAB, ABA, ABB, BAA, BAB, BBA, BBB

等等...... 对于长度为4的字符串,创建一个4维数组... 看,告诉你这是一个可怕的想法。

现在你只需要弄清楚如何填充数组,然后就可以使用像Array.deepToString这样的东西来打印它了...... 这太可怕了,但我喜欢不得不进入其他方面来回答这个问题。

<小时/>

另一种建模方法

对此问题进行建模的另一种可能方法是将其视为一组 链轮(如flip clock): Set of Linked Wheels

(忽略第三轮有2个B的一帧,这是一个错误:P)

箭头指向“轮子”设置的组合。

当第一个'wheel'完成它的旋转时,它会将下一个'wheel'递增1.这将允许你循环遍历所有可能的组合。

这种行为可以通过创建一个带有'value'属性和'rotation'方法的wheel类来实现。每次调用旋转时,它都会循环显示它的值。 创建一组这些轮类,并使其在第一个轮完成一个完整的旋转/循环时,它将增加第二个轮。然后,一旦第二个轮子完成一个旋转,第三个轮子将被调用,依此类推......

连接并打印程序每一步的轮子值,这应该有效。