[递归和栈] 合并编码

描述

给定一个合并编码后的字符串,返回原始字符串。

编码规则为: k[string],表示其中方括号内部的string重复 k 次,k为正整数且0 < k < 20。
可以认为输入数据中所有的数字只表示重复的次数k,且方括号总是满足要求的,例如不会出现像 3a 、 2[b 或 2[4] 的输入。

输入保证符合格式,且不包含空格。

输入

一行,一个长度为n(1 ≤ n ≤ 500)的字符串,代表合并编码后的字符串。

输出

一行,代表原始字符串。长度m满足0 ≤ m ≤ 1500。

样例输入

样例1:
3[abc]1[o]2[n]

样例2:
3[a2[c]]

样例输出

样例1:
abcabcabconn

样例2:
accaccacc

解题分析

这是一道需要使用栈来解决的问题。考虑到本题还和括号有关系,所以我们还需要在过程中使用数括号的算法来判断此时我们所在的括号的层数。在同一层数下的字符串应当被连接起来并压入栈中。考虑到我们输入格式的特殊,我们使用了字符串流 <sstream> 库来帮助我们更好地处理输入的字符串。当然我们先对输入的字符串进行一个增加空格的处理,此处还需要合理地使用substr函数来帮助我们处理。接着,我们把处理好的字符串扔进handle函数里面。维护好一个count变量,用于括号的计数和判断层数。此时我们的栈里面压入的应当是一个node节点,这个节点里保存着两个变量信息,一是字符串,二是该字符串所处的括号层数,也就是count。同时,我们使用两个栈来分别保存数字和字符串信息。遇见数字的时候,我们往数字栈里压入数字;遇见字符串的时候,我们往字符串栈里压入字符串。遇见正括号“[”时,我们增加计数器;同样的,如果我们遇见了反括号“]”,就减少计数器,同时开始我们的处理。处理的时候,我们弹出数字栈中的数字,也弹出字符串栈中的字符串,创建一个空字符串,然后将字符串栈中弹出的字符串倍长。同时,我们检查字符串栈中是否还有字符串,以及count是否是一个非0数,然后我们在字符串栈中找找是否有同一个括号内的字符串,如果有,我们把它们连接起来,然后作为一个节点放入字符串栈中。如果既不是“[”,也不是“]”,更不是数字的话,也就是说只是一个字符串,我们就直接把字符串和count压入栈内。接着,输出最终答案的时候,我们看看栈内空不空,如果不为空,我们就一直把栈内的字符串拼接起来,最后返回答案字符串即可。
 

代码实现

#include <iostream>
#include <cstdio>
#include <queue>
#include <bitset>
#include <map>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <unordered_map>
#include <unordered_set>
#include <cmath>
#include <vector>
#include <sstream>
#include <stack>

using namespace std;

struct node{
    string s0;
    int count;
};

string s;
stack<node> mystring;
stack<int> myint;

string handle(string tmps){
    int count=0;
    istringstream iss(tmps);
    string tmp;
    while(iss>>tmp){
    	//cout<<tmp<<endl;
        if(isdigit(tmp[0])){
            int tmpint=stoi(tmp);
            myint.push(tmpint);
        }
        else if(tmp=="["){
            count++;
        }
        else if(tmp=="]"){
            count--;
            int num=myint.top();
            myint.pop();
            node n0=mystring.top();
            mystring.pop();
            string s1="";
            for(int i=0;i<num;i++){
                s1+=n0.s0;
            }
            n0.s0=s1;
            node n1;
            int flag=1;
            do{
            	if(mystring.size() && count){
                n1=mystring.top();
                if(n1.count==count){
                    mystring.pop();
                    n0.s0=n1.s0+n0.s0;
                }
                else{
                    flag=0;
                }
            }
            else{
            	flag=0;
			}
            } while(flag);
            mystring.push({n0.s0,count});
        }
        else{
            mystring.push({tmp,count});
        }
    }
    string res="";
    while(!mystring.empty()){
        node ans=mystring.top();
        mystring.pop();
        res=ans.s0+res;
    }
    return res;
}

//3[a2[c3[b]]]

int main(){
	getline(cin,s);
	string input;
	for(int i=0;i<s.size();i++){
		if(isdigit(s[i])){
			if(!isdigit(s[i+1])){
				string tmp1=s.substr(0,i);
				string tmp2=s.substr(i+1);
				input=tmp1+' '+s[i]+' '+tmp2;
				i+=2;
			}
			else{
				string tmp1=s.substr(0,i);
				string tmp2=s.substr(i+2);
				input=tmp1+' '+s[i]+s[i+1]+' '+tmp2;
				i+=3;
			}
			s=input;
		}
		else if(s[i]=='[' || s[i]==']'){
			string tmp1=s.substr(0,i);
			string tmp2=s.substr(i+1);
			input=tmp1+' '+s[i]+' '+tmp2;
			i+=2;
			s=input;
		}
	}
    string ans = handle(s);
    cout<<ans<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值