hdu1274展開字符串(遞歸)

展開字符串

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1265    Accepted Submission(s): 563


Problem Description
在紡織CAD系統開發過程中,經常會遇到紗線排列的問題。
該問題的描述是這樣的:常用紗線的品種一般不會超過25種,所以分別可以用小寫字母表示不同的紗線,例如:abc表示三根紗線的排列;重複可以用數字和括號表示,例如:2(abc)表示abcabc;1(a)=1a表示a;2ab表示aab;如果括號前面沒有表示重複的數字出現,則就可認爲是1被省略了,如:cd(abc)=cd1(abc)=cdabc;這種表示方法非常簡單緊湊,也易於理解;但是計算機卻不能理解。爲了使計算機接受,就必須將簡單緊湊的表達方式展開。某ACM隊接受了此項任務。現在你就是該ACM隊的一員,請你把這個程序編寫完成。
已知條件:輸入的簡單緊湊表達方式的長度不超過250個字符;括號前表示重複的數不超過1000;不會出現除了數字、括號、小寫字母以外的任何其他字符;不會出現括號不配對等錯誤的情況(錯誤處理已由ACM其他隊員完成了)。
 

Input
本題有多個測試數據組,第一行輸入的就是數據組數N,接着就是N行表達式,表達式是按照前面介紹的意義書寫的。
 

Output
輸出時含有N行,每行對應一個輸入的表達式。
 

Sample Input
2 1(1a2b1(ab)1c) 3(ab2(4ab))
 

Sample Output
abbabc abaaaabaaaababaaaabaaaababaaaabaaaab
 

Author
Cai Minglun
 

Source

提交成功後的體會:
程序有些亂,但是總的思路就是簡單的遞歸應用。當然一定要記住在每一層遞歸中哪些參數是必須的,例如,我裏面寫的stemp,在每一層中都不一樣但初始值都是""  ,這樣在回溯的時候,可以將其作爲返回值進行累加stemp+stemp+stemp......(當然stemp在每一層中不太一樣)。還有就是選好遞歸終止條件,還有就是一般處理字符串都很麻煩,需多加細心,這個程序我大部分時間花在了調試上。。。>_<
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;

public class Main {
    static int n,len;
    static String sa,str;
    static char s[],c;
    static int[]keep = new int[1];
	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner(new InputStreamReader(System.in));
     //    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = sc.nextInt();//不知爲何在hdu oj上不能用BufferedReader中的br.readLine()/sc.nextLine()一用就錯>_<!!
         while(T-->0){
        	 sa  = sc.next();
        	 len = sa.length();
        	 s = (sa+"  ").toCharArray();//防止下面的指針超出數組界限溢出
        	 keep[0]=0;//記錄遞歸一次訪問最遠的位置
        	 
            System.out.println(dfs(0));
         }
	}
	private static String dfs(int i){
		 String stemp="";//每個遞歸中都有一個stemp,記錄該層裏的字符串,再將其返回
		
		 String digt = "";//,每層都有一個記錄數字的字符串
		 int w = 1;
		 boolean flag = true; 
		 for(c=s[i++] ; i<=len && c!=')'; c=s[i++] ){
			 
         	  w = 1;//默認爲的字母前參數爲 1
			 for( ;c>='0'&&c<='9'; c=s[i++]){//記錄數字
         	  digt +=c;
         	  flag = false;
         	 }
         	 if(!flag){//記錄數字
         		w = Integer.parseInt(digt);
         		digt = "";
         		flag = true;
         	 }
         	 if(c>='a'&&c<='z'){
         		 
         			while(w-->0)
         			  stemp =stemp+""+c;
         		}
         	 else if(c=='('){
         		 String  k = dfs(i);//臨時變量
         		    while(w-->0)
         		    	stemp = stemp + "" + k;
         		   
         		    i = keep[0];//字符串從遞歸最遠處,再開始進行
         	 }
          }
		 if(c==')')
		    keep[0]=i;//標記遞歸到的位置
		return stemp;
	}	
}
他人C/CC++代碼,供參考:
#include <iostream>
#include <cctype>
#include <cstring>
#include <string>
using namespace std;

string s;
int fun(int ith)
{
     int k,e;
     char c;
     for(c=s[ith++];ith<s.size()&&c!=')';c=s[ith++])//遞歸結束的條件是字符串結束或遇到右括號 
     {
          for(k=0;isdigit(c);c=s[ith++])
              k=k*10+c-'0';
          if(!k) k=1;
          if(c=='('){
              while(k--)
                  e=fun(ith);
              ith=e;//重置ith的值,到下層遞歸結束的位置 
     }
     else
     {
         while(k--)
             putchar(c);
     }
 }
 if(c==')') return ith;//返回本次讀到結尾的位置 
}
int main()
{
     int i,j,k,T;
     cin>>T;
     while(T--)
     {
          s.clear();
          cin>>s;
          fun(0);//進入遞歸 
          cout<<endl;
     }
     return 0;
}



發佈了145 篇原創文章 · 獲贊 27 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章