2016-06-08 65 views
3

該分配包括解壓縮字符串。特別是,如圖所示,代碼必須工作3個樣本。 Input - Output解壓更多嵌套字符串的字符串

我的代碼在這裏工作的樣本的前2個。但是,我無法拿出第三個樣本。可能我不明白遞歸的概念。你可以幫我嗎?

import java.util.Scanner; 

public class Compression4 { 

public static void main(String[] args) 
{ 
    Scanner in = new Scanner(System.in); 
    String input=in.next(); 
    System.out.println(uncompress(input)); 

} 
public static boolean flag = true; 

public static String uncompress(String compressedText) 
{ 
    return uncompress(compressedText, "", ""); 
} 
public static String getMultiple(String x, int N) { 
    if (N == 0) return ""; 

    return ""+x+getMultiple(x,N-1); 
} 
public static String uncompress(String text, String count, String output) 
{ 
    if (text.equals("")) 
    { 
     return output; 
    } 
    if(text.charAt(0) == '(') 
    {  
     int FirstIndex = text.indexOf("(")+1; 
     String inner = text.substring(FirstIndex, text.lastIndexOf(")")); 
     //System.out.println(inner); 
     flag = false; 
     return uncompress (inner, count, output); 

    } 
    else if (Character.isLetter(text.charAt(0))) 
    { 
     //letter case - need to take the count we have accrued, parse it into an integer and add to output 
     if (flag==true) 
     { 
       //System.out.println(count);// * text.charAt(0); 

       String s = String.valueOf(text.charAt(0)); 
       output += getMultiple(s,Integer.parseInt(count));       
       count ="1"; 
     }   
     else 
     { 
      //System.out.println(count);// * text.charAt(0); 
      output += getMultiple(text,Integer.parseInt(count)); 
      //System.out.println("output: "+output); 
      count="0"; 
     } 

    } 

    else if(Character.isDigit(text.charAt(0))) 
    { 
     //digit case - need to add to the count but keep as a string because must be parsed later 
     if(flag) 
      count += (""+text.charAt(0)); 
     else 
     { 
      count = "0"; 
      count += (""+text.charAt(0)); 

     } 

    } 

    //parse the *remainder* of the string, one character at a time, so pass in the substring(1) 

    return uncompress(text.substring(1), count, output); 

     } 
} 
+0

這是一個很好的作業!但你唯一的規格是三個樣品? – Aris2World

+0

我會添加一些指令 –

+0

從這些例子可以理解,我們假設字符串11ab中的數字11表示下一個符號被重複11次。如果我們想要一個更長的模式重複使用括號:string4(ab)中的數字4表示子串ab重複4次。所有未壓縮的字符串只由兩個符號a和b組成。雖然壓縮字符串也可以包含數字和圓括號,如上例所示。 –

回答

1

對不起,長代碼,但它更容易解釋與代碼比單詞。

前提:

  • 我認爲這個問題作爲一門語言的解釋器來渲染一個字符串
  • 語言簡單,功能如此遞歸解釋是可能的

算法階段:

  • 第一:標記表達式(在較高級別的abstr動作)
  • 第二:解析表達式只是標記化

遞歸:所述邏輯是基於語言的語法。

  • 基座箱子和遞歸例
  • 需要單個遞歸狀態(遞歸的局部變量,這些作爲參數傳遞給該遞歸方法)
  • 的狀態爲:一個遞歸的關鍵概念所有遞歸(遞歸的全局變量,某些特定遞歸中的讀/寫)

我已經提出了許多意見來解釋算法在做什麼。如果不清楚,我可以更好地解釋它。

import java.util.ArrayList; 
import java.util.List; 

public class TestStringDecompression { 

    // simpleExpr examples: a | b | 123a | 123b | 123(a) | 123(ab) | 123(ba) | (ab) | (ba) 
    // 11ab = aaaaaaaaaaab = = expression = simpleExpr simpleExpr = 11a b 
    // 4(ab) = abababab = expression = simpleExpr = 4(ab) 
    // 2(3b3(ab)) = bbbabababbbbababab = expression = compositeExpr = 2 (simpleExpr simpleExpr) = 2 (3b 3(ab)) 

    public static void main(String[] args) { 
     System.out.println(new StringInflater().inflate("11ab")); 
     System.out.println(new StringInflater().inflate("4(ab)")); 
     System.out.println(new StringInflater().inflate("2(3b3(ab))")); 
    } 

    public static class StringInflater { 

     // This store the position of the last parsed token 
     private int posLastParsedToken = 0; 

     public String inflate(String expression) { 
      return parse(tokenize(expression), 0, false); 
     } 

     /** 
     * Language tokens: 
     * <ul> 
     * <li>literals: 
     * <ul> 
     * <li>intLiteral = [0-9]*</li> 
     * <li>charLiteral = [ab]</li> 
     * </ul> 
     * </li> 
     * <li>separators: 
     * <ul> 
     * <li>leftParen = '('</li> 
     * <li>rightParen = ')'</li> 
     * </ul> 
     * </li> 
     * </ul> 
     */ 
     private Object[] tokenize(String expression) { 
      List<Object> tokens = new ArrayList<Object>(); 
      int i = 0; 
      while (i < expression.length()) { 
       if ('0' <= expression.charAt(i) && expression.charAt(i) <= '9') { 
        String number = ""; 
        while ('0' <= expression.charAt(i) && expression.charAt(i) <= '9' && i < expression.length()) { 
         number += expression.charAt(i++); 
        } 
        tokens.add(Integer.valueOf(number)); 
       } else { 
        tokens.add(expression.charAt(i++)); 
       } 
      } 
      return tokens.toArray(new Object[tokens.size()]); 
     } 

     /** 
     * Language syntax: 
     * <ul> 
     * <li>simpleExpr = [intLiteral] charLiteral | [intLiteral] leftParen charLiteral+ rightParen</li> 
     * <li>compositeExpr = [intLiteral] leftParen (simpleExpr | compositeExpr)+ rightParen</li> 
     * <li>expression = (simpleExpr | compositeExpr)+</li> 
     * </ul> 
     */ 
     private String parse(Object[] tokens, int pos, boolean nested) { 
      posLastParsedToken = pos; 
      String result = ""; 
      if (tokens[pos] instanceof Integer) { 
       /** it's a intLiteral */ 
       // get quantifier value 
       int repetition = (int) tokens[pos]; 
       // lookahead for (
       if (tokens[pos + 1].equals("(")) { 
        // composite repetition, it could be: 
        // simpleExpr: "[intLiteral] leftParen charLiteral+ rightParen" 
        // compositeExpr: "[intLiteral] leftParen (simpleExpr | compositeExpr)+ rightParen" 
        result = parse(tokens, pos + 1, true); 
       } else { 
        // simple repetition, it could be: 
        // simpleExpr: [intLiteral] charLiteral 
        result = parse(tokens, pos + 1, false); 
       } 
       result = repeat(result, repetition); 
       // evaluate the rest of the expression because syntax allows it 
       if (posLastParsedToken + 1 == tokens.length) { 
        // end of the expression 
        return result; 
       } else { 
        // there are other simpleExpr or compositeExpr to parse 
        return result + parse(tokens, posLastParsedToken + 1, false); 
       } 
      } else if (tokens[pos].equals('(')) { 
       /** it's a leftParen */ 
       // an open paren means what follow this token is considered nested (useful for string to treat as char sequence) 
       return parse(tokens, pos + 1, true); 
      } else if (tokens[pos].equals(')')) { 
       /** it's a rightParen */ 
       // a closed paren, nothing to render 
       return ""; 
      } else { 
       /** it's a charLiteral */ 
       if (nested) { 
        // it's nested between paren, so more parsing is requested to consume next charLiteral or next simpleExpr or compositeExpr 
        return tokens[pos] + parse(tokens, pos + 1, nested); 
       } else { 
        // it's not nested between paren, return charLiteral as is 
        return "" + tokens[pos]; 
       } 
      } 
     } 

     private String repeat(String s, int repetition) { 
      StringBuilder result = new StringBuilder(); 
      for (int i = 0; i < repetition; i++) { 
       result.append(s); 
      } 
      return result.toString(); 
     } 

    } 

}