Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.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 查找包含给定字符串的所有组合的最短文本_Java_Algorithm - Fatal编程技术网

Java 查找包含给定字符串的所有组合的最短文本

Java 查找包含给定字符串的所有组合的最短文本,java,algorithm,Java,Algorithm,给定一个字符串,查找另一个包含输入字符串所有组合的字符串 例如: 如果输入字符串=23,则其组合为[22,23,32,33] 包含上述所有组合的字符串之一是22233233,但这不是最短的。最短的是22332 算法应该足够通用,可以处理任何大小的输入字符串。假设输入不太大,输出将保持在正常的int/string/jvm等大小。还假设输入字符串将只包含来自英语的字母数字字符 我尝试了以下算法,但似乎不起作用: 1查找字符串的所有组合=[22,23,32,33] 2构建前缀映射[2:{22,23},

给定一个字符串,查找另一个包含输入字符串所有组合的字符串

例如:

如果输入字符串=23,则其组合为[22,23,32,33]

包含上述所有组合的字符串之一是22233233,但这不是最短的。最短的是22332

算法应该足够通用,可以处理任何大小的输入字符串。假设输入不太大,输出将保持在正常的int/string/jvm等大小。还假设输入字符串将只包含来自英语的字母数字字符

我尝试了以下算法,但似乎不起作用:

1查找字符串的所有组合=[22,23,32,33]

2构建前缀映射[2:{22,23},3:{32,33}]

3从前缀映射中的任意组合和查找后缀开始

示例:以22开头,其后缀为2 从前缀映射中,对应于2的值为22和23。 在这里选择一个不是当前所选单词的单词,它将给出23

4将所选单词的后缀添加到当前字符串,这将得到223

重复5次。 所以我将得到223的后缀=3 来自前缀映射,3:{32,33} 随便选一个,比如说32 追加到当前字符串以获取2232

6如果没有其他匹配项,则追加到当前字符串。这是223233

然而,答案应该是22332,因为这是最短的

以下是我迄今为止编写的完整代码:

public class TextContainingAllPermutations
{
    static String input = "ABC";

    public static void main (String args[])
    {
        int suffixLen = input.length()-1;
        Set<String> combinations = getCombinations();
        while (suffixLen > 0 && combinations.size() > 1)
        {
            Map<String, List<String>> suffixToWords = getPrefixMap(combinations, suffixLen);
            String someWordsString = combinations.iterator().next();
            combinations.remove(someWordsString);
            Set<String> combinations2 = new HashSet<String>();

            while (combinations.size() > 0)
            {
                String suffix = someWordsString.substring(someWordsString.length()-suffixLen);
                List<String> words = suffixToWords.get(suffix);
                if (words == null || words.size()==0)
                {
                    combinations2.add(someWordsString);
                    System.out.println (someWordsString);
                    if (combinations.size() == 0)
                        break;
                    someWordsString = combinations.iterator().next();
                    combinations.remove(someWordsString);
                }
                else
                {
                    String w = words.get(words.size()-1);
                    words.remove(words.size()-1);
                    combinations.remove(w);
                    if (someWordsString.indexOf(w) == -1)
                        someWordsString += w.charAt(w.length()-1); // append last char
                }
            }
            combinations2.add(someWordsString);
            System.out.println (someWordsString);
            combinations = combinations2;
            suffixLen--;
        }
    }

    private static Map<String, List<String>> getPrefixMap(Set<String> combinations, int suffixLen)
    {
        Map<String, List<String>> suffixToWords = new HashMap<String, List<String>>();
        for (String s: combinations)
        {
            String suffix = s.substring(0,suffixLen);
            if (!suffixToWords.containsKey(suffix))
            {
                suffixToWords.put(suffix, new ArrayList<String>());
            }
            suffixToWords.get(suffix).add(s);
        }
        return suffixToWords;
    }

    static Set<String> getCombinations()
    {
        char[] inputChars = input.toCharArray();
        int N = (int)Math.pow(input.length(), input.length());
        Set<String> combinations = new HashSet<String>(N);
        for (int i=0; i<N; i++)
        {
            char[] binary = padZeroes(Integer.toString(i, input.length())).toCharArray();

            String combination = "";
            for (int j=0; j<inputChars.length; j++)
            {
                char c = binary[j];
                int index = c - '0';
                char inputChar = inputChars[index];
                combination = inputChar + combination;
            }

            System.out.println (new String(binary) + " = " + combination);
            combinations.add(combination);
        }
        return combinations;
    }

    private static String padZeroes(String s)
    {
        int j = input.length()-s.length();
        for (int i=0; i<j; i++)
            s = '0' + s;
        return s;
    }
}

这不是一个家庭作业问题。

你要找的基本上是一个家庭作业。De Bruijn序列Bk,n是一个循环序列,它包含一组k符号中长度为n的所有可能子序列,每个子序列恰好出现一次。序列的长度正好是kn

最小非循环序列可通过在任意点中断循环,然后将前n-1符号复制到末尾,生成长度为kn+n-1的序列,这显然是最小的

有多种技术可以生成De Bruijn序列。最简单的描述方法是,de Bruijn序列由字母表上所有长度除以n的字母按字典顺序串联而成。林登词是一个序列,它在词典编纂上先于自身的任何旋转。这意味着林登这个词是非周期的

有一种简单的算法可以按字典顺序在字母表上生成最大长度为n的Lyndon单词:

从仅由集合中按字典顺序排列的第一个字符组成的长度开始。 尽可能长地,通过循环重复上一个单词,直到长度n,形成下一个单词,如有必要,丢弃上一次重复中的额外符号,然后通过以下方式递增该单词: 只要单词中的最后一个符号是字母表中词典学上最大的符号,就将其删除。 如果单词中仍有符号,请将最后一个符号更改为词典编纂的后续符号。如果单词中没有留下任何符号,生产就完成了。 为了使De Bruijn序列为n阶,我们产生了上面的Lyndon单词序列,但我们只保留长度除以n的单词序列。由于几乎所有最大长度为n的Lyndon字实际上都是长度为n的,因此该算法可以被视为每个符号O1,或整个序列Okn


在问题要求的特定情况下,k==n.

您所寻找的基本上是一个。De Bruijn序列Bk,n是一个循环序列,它包含一组k符号中长度为n的所有可能子序列,每个子序列恰好出现一次。序列的长度正好是kn

最小非循环序列可通过在任意点中断循环,然后将前n-1符号复制到末尾,生成长度为kn+n-1的序列,这显然是最小的

有多种技术可以生成De Bruijn序列。最简单的描述方法是,de Bruijn序列由字母表上所有长度除以n的字母按字典顺序串联而成。林登词是一个序列,它在词典编纂上先于自身的任何旋转。这意味着林登这个词是非周期的

有一种简单的算法可以按字典顺序在字母表上生成最大长度为n的Lyndon单词:

从仅由集合中按字典顺序排列的第一个字符组成的长度开始。 尽可能长地,通过循环重复上一个单词,直到长度n,形成下一个单词,如有必要,丢弃上一次重复中的额外符号,然后通过以下方式递增该单词: 只要单词中的最后一个符号是字母表中词典学上最大的符号,就将其删除。 如果单词中仍有符号,请将最后一个符号更改为词典编纂的后续符号。如果工作中没有留下任何符号 d、 生产结束了。 为了使De Bruijn序列为n阶,我们产生了上面的Lyndon单词序列,但我们只保留长度除以n的单词序列。由于几乎所有最大长度为n的Lyndon字实际上都是长度为n的,因此该算法可以被视为每个符号O1,或整个序列Okn


在问题要求的特定情况下,k==n.

您确定了什么将起作用还是不起作用?这个问题似乎离题了,因为它是一个“给我代码”问题。你可能应该这样做。这可能不是家庭作业问题,我愿意让你相信我的怀疑,但是……你这方面没有任何努力的迹象,所以很难说服我们不这样做。@Makoto,我在这里更新了我的算法。我可以把完整的代码也放在这里,以显示我的尝试。这肯定会有助于你的事业。这也有助于说明为什么你认为它不起作用,因为它不起作用并不能很好地描述一个问题。尽管我不得不承认,我在工作中使用过一两次,但向问题中添加更多信息通常会给出令人满意的答案。你确定什么是有效的还是无效的?这个问题似乎离题了,因为它是一个“给我代码”问题。你可能应该这样做。这可能不是家庭作业问题,我愿意让你相信我的怀疑,但是……你这方面没有任何努力的迹象,所以很难说服我们不这样做。@Makoto,我在这里更新了我的算法。我可以把完整的代码也放在这里,以显示我的尝试。这肯定会有助于你的事业。这也有助于说明为什么你认为它不起作用,因为它不起作用并不能很好地描述一个问题。尽管我很讨厌承认,我在工作中用过一两次,但在问题中添加更多信息通常会给出令人满意的答案。