簡體   English   中英

Java - 獲取字符串的每個 Substring 的所有排列、子串和排列

[英]Java - Get All Permutations, Substrings and Permutations of every Substring of a String

首先,我首先要說英語不是我的第一語言,所以對於任何糟糕的解釋,我深表歉意。

我想知道如何獲得具有這么多不同順序的字符串的每一個 substring。 在你告訴我這個問題之前有人問過之前,我想說我看到的這個任務的幾乎每個代碼實現都不包含重復項。 但是假設我有一個字符串“環境”,我想要每一個 substring,包括“ment”,“met”,“ten”,“net”,“note”,“more”

這是我寫的function。

     public static ArrayList<String> getAllSubstringsOfAString(String inputString)
     {
     ArrayList<String> allSubstrings = new ArrayList<String>();
     String sub;
     for(int i = 0; i < inputString.length(); i++)
     {
        for (int j = 1; j <= inputString.length() - i; j++)
        {
            sub = inputString.substring(i , i + j);
            allSubstrings.add(sub);
        }
      }
      return allSubstrings;
     }

當我運行這個 function

    public static void main(String[] args) throws IOException {
    ArrayList<String> allSubStrings = getAllSubstringsOfAString("environment");
    for (String allSubString : allSubStrings) {
        System.out.println(allSubString);
    }

它打印出來

    e
    en
    env
    envi
    envir
    enviro
    environ
    environm
    environme
    environmen
    environment
    n
    nv
    nvi
    nvir
    nviro
    nviron
    nvironm
    nvironme
    nvironmen
    nvironment
    v
    vi
    vir
    viro
    viron
    vironm
    vironme
    vironmen
    vironment
    i
    ir
    iro
    iron
    ironm
    ironme
    ironmen
    ironment
    r
    ro
    ron
    ronm
    ronme
    ronmen
    ronment
    o
    on
    onm
    onme
    onmen
    onment
    n
    nm
    nme
    nmen
    nment
    m
    me
    men
    ment
    e
    en
    ent
    n
    nt
    t

這只是我想要的一小部分。 我希望 function 能夠按每個順序獲取子字符串。 例如,如果我希望它包含像“net”、“ten”、“never” etc 這樣的字符串,因為它們都是“environment”這個詞的子字符串。 我必須對我的 function 進行哪些更改才能達到此目的?

另外,由於我是 Java 初學者,我想知道我的代碼是否寫得好,我可以對我的代碼進行哪些更改以使其性能更好,看起來更好,並遵循常見的 Java 編碼約定。

提前致謝

1)生成所有子串(你已經得到了那個部分)

2)為每個子串生成所有它的排列 - 你可以使用位向量遞歸或迭代地執行它(這里已經顯示了如何做到這一點,快速谷歌搜索也會給你一些提示)

3)將所有內容添加到最終列表中,這將為您提供已有的內容,反轉版本以及所有其他排列

例如,使用“abc”,您將獲得:

  • a(1個字符,1個排列)
  • ab(子串)
    • ba(子串置換)
  • abc(子串)
    • bca(子串置換)
    • bac(子串置換)
    • acb(substring permutation)
    • cab(子串置換)
    • cba(子串置換)

請注意,計算可能需要一些時間,當字符串為N時,它有N! 排列,你將為每個子字符串調用它,所以N次將產生O(N * N!)時間復雜度。

正如@ PM77-1指出的那樣,如果我們的字符串有像abcabc這樣的重復子字符串,這可能會做很多不必要的工作。 在每次新迭代之前的情況下,您可以檢查給定的子字符串是否已經在集合中(是的,您將結果列表更改為具有O(1)查找的集合)並且如果它已經存在則跳過它。

在另外一個問題的幫助下,我把它扔到了一起。

public static void main(String[] args) {
    List<String> list = perms("codes");
    list.forEach(s -> System.out.println(s));
}

public static List<String> perms(String string) {

    List<String> result = new ArrayList<String>();
    char[] values = string.toCharArray();
    for (int width = 1; width <= values.length; width++) { // for every length
        int stack[] = new int[width];
        for (int i = 0; i < stack.length; i++) { // start from a specific point without duplicates
            stack[i] = stack.length - i - 1;
        }
        int position = 0;
        while (position < width) {

            position = 0;
            StringBuilder sb = new StringBuilder();
            while (position < width) { // build the string
                sb.append(values[stack[position]]);
                position++;
            }
            result.add(sb.toString());
            position = 0;
            while (position < width) {
                if (stack[position] < values.length - 1) {
                    stack[position]++;
                    if (containsDuplicate(stack) == false)
                        break;
                    else
                        position = 0;
                } else {
                    stack[position] = 0;
                    position++;
                }
            }
        }
    }
    return result;
}

private static boolean containsDuplicate(int[] stack) {
    for (int i = 0; i < stack.length; i++) {
        for (int j = 0; j < stack.length; j++) {
            if (stack[i] == stack[j] && i != j) {
                return true;
            }
        }
    }
    return false;
}

它不會重復使用該單詞中的字母,除非該單詞包含該字母兩次。
在這種情況下會有雙打。
它不使用遞歸,因此堆棧溢出不會成為問題。

下面的程序返回所有可能的子集及其各自的排列。

  • 例如,對於值abcd@1234 ,它將從中返回986410 個可能的值。
  • [注意] :對於包含相同字符的排列,它的工作方式會有所不同。
    aaaa@1234的示例它將從中返回6850 個可能的值。
public class PermutationWithSub {
    public void subStrings(String string){
        List<List<Character>> listList = new ArrayList<>();
        listList.add(new ArrayList<>());
        ArrayList<String> subStringArraylist = new ArrayList<>();
        ArrayList<String> bruteList = new ArrayList<>();
        for (char c:string.toCharArray()){
            int size = listList.size();
            for (int i=0;i<size;i++){
                List<Character> temp = new ArrayList<>(listList.get(i));
                temp.add(c);
                listList.add(temp);
            }
        }
        for (List<Character> characterList : listList) {
            StringBuilder stringBuilder = new StringBuilder();
            for (Character character : characterList) {
                stringBuilder.append(character);
            }
            subStringArraylist.add(stringBuilder.toString());
        }
        for (String str:subStringArraylist){
            List<List<Character>> listListChar = permute(str);
            for (List<Character> listChar:listListChar){
                StringBuilder stringBuilder = new StringBuilder();
                for (Character character:listChar){
                    stringBuilder.append(character);
                }
                bruteList.add(stringBuilder.toString());
            }
        }
        listList.clear();
        subStringArraylist.clear();
        for (String str:bruteList){
                System.out.println(str);
        }
    }
    public List<List<Character>> permute(String string){
        List<List<Character>> powerSet = new ArrayList<>();
        generateSet(powerSet,new ArrayList<>(),string.toCharArray());
        return powerSet;
    }

    private void generateSet(List<List<Character>> powerSet, List<Character> temp, char[] chars) {
        if (temp.size()==chars.length){
            powerSet.add(new ArrayList<>(temp));
        }else {
            for (char aChar : chars) {
                if (temp.contains(aChar))
                    continue;
                temp.add(aChar);
                generateSet(powerSet, temp, chars);
                temp.remove(temp.size() - 1);
            }
        }
    }
    public static void main(String[] args) {
        MyBruteForceTool myBruteForceTool = new MyBruteForceTool();
        myBruteForceTool.subStrings("abcd@1234");
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM