字符串解压

字符串解压

题目来源:2020年“华为杯”G题。
题目描述:
我们规定一种字符串的压缩方法,用[]将重复的部分括起来,[]前面的数字代表重复的这部分串重复了多少次,可以想到给定一个字符串用这种方式压缩的结果会有多种,比如 aaaa可以压缩为4[a],也可以压缩为aa2[a],或者2[2[a]],但是给定一个压缩好的字符串它的原串是唯一的。
输入描述:
输入数据有多组,总组数不超过100组。每组输入一行,一个压缩后的字符串,长度 len\ len len满足1≤len≤2001 \leq len \leq 2001≤len≤200,输入的字符串中只包含字母、数字和“[]”,保证输入合法。
输出描述:
对于每组输入输出一行,表示解压后的字符串。
样例:
输入:
3[a2[b]c]
2[2[a]]
aac5[]b
输出:
abbcabbcabbc
aaaa
aacb
备注:
保证每个’['前一定是数字(非负整数),且小于10,原串只由字母构成,数字仅做计数用途。

这题其实写起来挺水的,但是那天刚考完英语,脑袋晕晕的,搞这题搞了半天……菜是原罪。不过还好在封榜前三分钟搞出来了,具体思路如下:
考虑一个“递归”过程,遇到“[”就进行递归,遇到“]”就返回(当然,全部遍历完了也要返回),用“[”前边的数字对遍历到的字符串进行(该数字-1)次的复制(最外边的那个没有“[]”的字符串,其数字可看为“1”)。问题在于“回溯”后,遍历的下标要往前移动几格,利用括号匹配的思想,将下标移至“栈为空”的位置即可(如下):

stack<int>st;
st.push(1);
while(i<len&&!st.empty())
{
    i++;
    if(ss[i]=='[')
       st.push(1);
    if(ss[i]==']')
       st.pop();
}
i++;

完整代码如下:

#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3)
#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <sstream>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pll;
typedef pair<int,int> pii;
typedef queue<int> q_i;
typedef queue<string> q_s;
typedef queue<double> q_d;
typedef queue<ll> q_ll;
typedef queue<char> q_c;
typedef priority_queue<int> pq_i;
typedef priority_queue<string> pq_s;
typedef priority_queue<double> pq_d;
typedef priority_queue<ll> pq_ll;
typedef stack<int> s_i;
typedef stack<string> s_s;
typedef stack<double> s_d;
typedef stack<ll> s_ll;
typedef stack<char> s_c;
typedef map<ll,ll> m_ll_ll;
typedef map<int,ll> m_i_ll;
typedef map<int,int> m_i_i;
typedef map<string,ll> m_s_ll;
typedef map<char,int> m_c_i;
typedef map<char,ll> m_c_ll;
const ll INF=0x3f3f3f3f;
#define rep(i,l,r) for(register int i=l;i<=r;i++)
#define per(i,l,r) for(register int i=r;i>=l;i--)
#define eif else if
#define mm(dp) memset(dp,0,sizeof(dp))
#define mm1(dp) memset(dp,-1,sizeof(dp))
#define mm2(dp) memset(dp,0x3f,sizeof(dp))
#define IT set<int>::iterator
#define fs(n) fixed<< setprecision(n)
const double e=2.71828182845;
const int N=1e8;
const int M=1e7;
const ll mod=1e9+7;
const ll inf=1e11+7;
const double pi = acos(-1.0);
string fun(int num,string ss)
{
    //cout<<num<<endl;
    int len=ss.size();
    string ss1="";
    int nm=0;
    for(int i=0;;i<len)
    {
        if((ss[i]>='a'&&ss[i]<='z')||(ss[i]>='A'&&ss[i]<='Z'))
        {
            ss1+=ss[i];
            i++;
        }
        eif(ss[i]>='0'&&ss[i]<='9')
        {
            nm=(ss[i]-'0');
            i++;
        }
        eif(ss[i]=='[')
        {
            string ss0=fun(nm,ss.substr(i+1,len-i-1));
            ss1=ss1+ss0;
            int siz=ss0.size();
            //cout<<i<<endl;
            stack<int>st;
            st.push(1);
            //i++;
            while(i<len&&!st.empty())
            {
                i++;
                if(ss[i]=='[')
                    st.push(1);
                if(ss[i]==']')
                    st.pop();
            }
            i++;
            //cout<<ss1<<endl;
            //cout<<i<<"..."<<" "<<ss1<<endl;
        }
        eif(ss[i]==']')
        {
            string s0="";
            int siz=ss1.size();
            rep(j,1,num)
            {
                s0+=ss1;
            }
            ss1=s0;
            i++;
            break;
            //cout<<ss1<<endl;
            //ss1+=ss.substr(i+1,len-i-1);
        }
        //cout<<i<<" "<<len<<" "<<ss1<<endl;
        if(i>=len)
            break;
    }
    return ss1;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    string str;
    while(cin>>str)
    {
        int len=str.size();
        string str1=fun(1,str);
        cout<<str1<<endl;
        //cout<<str<<endl;
    }
    return 0;
}
//3[aa2[b]2[c]]
//3[a2[b]c]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值