P1928 外星密碼 遞迴/模擬
題目描述
有了防護傘,並不能完全避免 2012 的災難。地球防衛小隊決定去求助外星種族的幫 助。經過很長時間的努力,小隊終於收到了外星生命的回信。但是外星人發過來的卻是一 串密碼。只有解開密碼,才能知道外星人給的準確回覆。解開密碼的第一道工序就是解壓 縮密碼,外星人對於連續的若干個相同的子串“X”會壓縮為“[DX]”的形式(D 是一個整 數且 1≤D≤99),比如說字串“CBCBCBCB”就壓縮為“[4CB]”或者“[2[2CB]]”,類 似於後面這種壓縮之後再壓縮的稱為二重壓縮。如果是“[2[2[2CB]]]”則是三重的。現 在我們給你外星人傳送的密碼,請你對其進行解壓縮。
輸入格式
第一行:一個字串
輸出格式
第一行:一個字串
輸入輸出樣例
輸入 #1AC[3FUN]輸出 #1
ACFUNFUNFUN
說明/提示
【資料範圍】
對於 50%的資料:解壓後的字串長度在 1000 以內,最多隻有三重壓縮。
對於 100%的資料:解壓後的字串長度在 20000 以內,最多隻有十重壓縮。 對於 100%的資料:保證只包含數字、大寫字母、’[‘和’]‘
看到這題的第一反應就是,這不是一道大模擬嘛
大概思路是先將整個字串先讀入STR[]之中,然後將其分成兩部分,[]裡面的部分和[]外面的部分,對於[]裡面的部分用string類裡的find()函式去找[和],然後從內層開始一層一層拆出來
一開始是用迴圈去做,非常非常麻煩,程式碼不貼了,看得人直噁心
後來想到這是一道遞迴題目,於是對上述思路進行優化
我們挑選一段[]中的內容來分析
核心程式碼:now=s.find('[',now);
now表示的是當前[的位置,上述遞迴的邊界條件是(now<s.find(']',r)),這個r就是是第一個now
這樣的遞迴之後我們就能找到最裡面的[],然後開始拆包
我們從頭開始走一遍
我們在遞迴內部定義三個變數,int n string s,str
n表示重複次數,s表示當前[]內的最終的答案字串(也就是拆完包之後的結果),str表示當前[]的內部第一個[]拆包出來的結果
首先讀取重複次數,令ans=1,從當前[]的左端點[一路向右端點]掃描,讀入一位(>='0'&&<='9')的字元就將ans乘10並加上當前數字
然後立刻(就是在讀取完次數的下一行、)開始遞迴呼叫,去找下一個[]部分,並將其結果存在str當中,遇到了邊界條件之後返回一個空字元
now=s.find('[',now);
str=solve(now);
邊界條件:(now<STR.find(']',r))
這樣一層層下來我們就會找到最裡面的[]部分,讀取完重複次數後繼續掃描,遇到一個非]的字元就把其拼接在s後面,
s+=STR[i];
直到遇到]為止,此時我們已經獲得了需要重複的字串s,然後將其重複ans次後返回
string s1=“”;
while(ans--)s1+=s;
return s1;
此時我們回到了上一層的
str=solve(now);
順便更新一下當前層的]的位置,儲存在r中
r=STR.find(']',r);
下一層[]中拆包後的結果已經儲存在str中了,我們還是繼續掃描,遇到一個非[的字元就把它拼接在s後面(此時的s已經是這一層[]中的s),遇到[的時候就把str直接拼接在當前s的後面,然後找到與其對應的],從]之後繼續從STR[]中讀取字元,直到遇到這一層的](也就是走到r的位置),然後重複以上步驟,將這一層的s重複這一層的重複次數之後返回,並儲存在上一層的str中,然後逐層遞歸回去,最後的s裡面儲存的就是徹底拆完包之後的字串
到這裡最複雜的[]內的拆包部分就寫完了,剩下的[]之外的部分就不多說了,沒難度了已經
然後我在看題解的時候發現了更好的做法,思路和我上面說的一樣,但是人家是邊讀入邊完成的工作,也就是說,省去了用find()一個個查詢[]區間並且反覆更新now和r這些繁瑣的步驟,這裡就貼別人的優秀程式碼了,我自己那個奇醜無比的就不拿出來獻醜了
#include<bits/stdc++.h> using namespace std; string read() { int n; string s="",s1; char c; while (cin>>c)//一直讀入字元,直到Ctrl+z { if (c=='[') { cin>>n;//讀入D s1=read();//讀入X while (n--) s+=s1;//重複D次X //注:上面不能寫成while (n--) s+=read(); } else { if (c==']') return s;//返回X else s+=c;//如果不是'['和']',那就是X的一個字元,所以加進X } } } int main()//巨短主函式 { cout<<read(); return 0; }
此程式碼來自a1_1