3

我发现了很多类似的问题,但主要是关于正则表达式,而不是我想要做的。

Given a string = "(content4(content3(content2(content1...))))

我想先获得叶括号内容(content1 ...),然后再上一级(content2(content1 ...)),然后再上一级......等等。我有一些非常复杂的解决方案,但我想知道是否没有更简单的方法。这似乎最好递归解决,但我还找不到一个好的解决方案。有人可能已经解决了类似的问题。大家有什么想法或建议吗?

提前谢谢你的帮助,我很感激

添加 :

字符串也可以如下所示:

string = "(content4(content3(content2(content1...);content5(content6...))))"

4

5 回答 5

3

使用堆栈。

将您的字符串分成 3 种类型的元素。

一个。左括号。

湾。两个连续左括号之间的字符串,或者如果没有第二个左括号,则为左括号和直接右括号之间的字符串。

C。右括号

该方法将类似于以下内容。

  1. 将左括号压入栈顶。

  2. 考虑到第二个左括号确实存在,将两个左括号之间的字符串推入堆栈顶部,然后转到第 3 步,否则将左右括号之间的字符串推入堆栈顶部,然后转到第 4 步。

  3. 将字符串(两个左括号之间的字符串)之后的左括号压入堆栈顶部。重复步骤 1 到 3,直到遇到右括号。

  4. 遇到右括号后,从堆栈中删除顶部两个元素,即字符串(两个左括号之间的字符串)或字符串(左括号和右括号之间的字符串)和左括号,并调整顶部索引和字符串索引。现在你有了内容 1。

  5. 重复第 4 步,直到获得所有内容。

于 2013-03-20T15:59:42.363 回答
1

这似乎与理智的输入非常有效。我没有测试过奇怪的。

public static void main(String args[]) {
  ArrayList<String> split = split("(content4(content3(content2(content1...))))");
  System.out.println("Split: " + split);
}

// Standard set of braces.
private static final String openBraces = "({[<";
// Matching close set.
private static final String closeBraces = ")}]>";

public static ArrayList<String> split(String s) {
  // Default to splitting with my standard set of braces.
  return split(s, openBraces, closeBraces);
}

// Holds the start of an element and which brace started it.
private static class Start {
  // The brace number from the braces string in use.
  final int brace;
  // The position in the string it was seen.
  final int pos;

  // Constructor.
  public Start(int brace, int pos) {
    this.brace = brace;
    this.pos = pos;
  }

  @Override
  public String toString() {
    return "{"+openBraces.charAt(brace)+","+pos+"}";
  }
}

public static ArrayList<String> split(String s, String open, String close) {
  // The splits.
  ArrayList<String> split = new ArrayList<String>();
  // The stack.
  ArrayList<Start> stack = new ArrayList<Start>();
  // Walk the string.
  for (int i = 0; i < s.length(); i++) {
    // Get the char there.
    char ch = s.charAt(i);
    // Is it an open brace?
    int o = open.indexOf(ch);
    // Is it a close brace?
    int c = close.indexOf(ch);
    if (o >= 0) {
      // Its an open! Push it.
      stack.add(new Start(o, i));
    } else if ( c >= 0 && stack.size() > 0 ) {
      // Pop (if matches).
      int tosPos = stack.size() - 1;
      Start tos = stack.get(tosPos);
      // Does the brace match?
      if ( tos.brace == c) {
        // Matches!
        split.add(s.substring(tos.pos, i+1));
        // Done with that one.
        stack.remove(tosPos);
      }
    }
  }
  return split;
}

印刷:

Split: [(content1...), (content2(content1...)), (content3(content2(content1...))), (content4(content3(content2(content1...))))]
于 2013-03-20T16:52:56.223 回答
0

我很久以前用 HyperTalk 做过,但算法框架保持不变:

1 - 每次遇到左大括号时,将 1 添加到括号计数器 2 - 对右括号执行相反的操作

每次找到第一个左括号时,存储它的位置+1,对右括号执行相同的位置-1。

当找到右括号时,提取子字符串并对其进行递归。

如果您想首先获得更多嵌套的“叶子”,只需使用带有括号位置的列表,然后向后读取您的列表(或使用堆栈)。

但请注意:这种技术只会给你带来第一个孩子。

于 2013-03-20T15:52:22.453 回答
0

这是我通过在大括号两侧设置头尾标志来解决此问题的方法,但真正经典的方法是使用堆栈。

public static void main(String[] argv) {
    String str = "(content4(content3(content2(content1...))))";
    int head = str.lastIndexOf("(");
    int tail = 0;

    while (head != -1) {
        // stop loop if the brace mismatch
        if (str.substring(tail, str.length()).indexOf(")") == -1)
            break;
        tail += str.substring(tail, str.length()).indexOf(")") + 1;
        String res = str.substring(head, tail);
        System.out.println(res);
        head = str.substring(0, head).lastIndexOf("(");

    }
}
于 2013-03-20T17:18:43.410 回答
0

好的,这是解决您问题的好方法。

    String str = "(content4(content3(content2(content1...))))";
    str = str.replaceFirst("\\(", "");
    String[] results = str.split("\\)")[0].split("\\(");

    int l = results.length;
    for (int j = 0; j < l / 2; j++) {
        String temp = results[j];
        results[j] = results[l - j - 1];
        results[l - j - 1] = temp;
    }

    for (String string : results) {
        System.out.println(string);
    }

代码说明:

  • 首先我们删除第一个“(”,因为它会导致最后出现一个空字符串。
  • 将字符串拆分为 ")" 并在索引 0 处获取字符串以保留我们的数据:

    字符串现在看起来像这样:

内容 4(内容 3(内容 2(内容 1...

  • 然后通过围绕“(”再次拆分,我们的内容被反向排列。
  • 最后我们反转数组
于 2013-03-20T16:18:31.767 回答