SCAU18941 数据解压(压缩算法)




腾讯2020校园招聘-后台 第一题
小Q想要给他的朋友发送一个神秘字符串,但是他发现字符串的过于长了,
于是小Q发明了一种压缩算法对字符串中重复的部分进行了压缩,
对于字符串中连续的m个相同字符串S将会压缩为m|S,例如字符串ABCABCABC将会被压缩为[3|ABC],
现在小Q的同学收到了小Q发送过来的字符串,你能帮助他进行解压缩么?



解题建议:

(1)由于涉及到字符串的重复,尽量不要再使用C语言的字符数组,用C++的string类型会更容易实现。
(2)多层嵌套的情况,必须先求出内层再求出外层,显而易见可用递归算法或栈解决,建议递归。
(3)当确定s[i]是一个数字字符时,可以用如下C++代码获取字符串中的整数
int sum=0;
while(isdigit(s[i]))
sum=sum*10+s[i++]-‘0’;




输入格式

输入第一行包含一个字符串S,代表压缩后的字符串。
S的长度<=1000;
S仅包含大写字母、[、]、|;
解压后的字符串长度不超过100000;
压缩递归层数不超过10层;





输出格式

输出一个字符串,代表解压后的字符串。

输入样例 HG[3|B[2|CA]]F

输出样例 HGBCACABCACABCACAF





解题思路

输入内容并不复杂,仅包含大写字母、“[”、“]”、“|”还有数字字符;

这些信息分开保存,大写字母和 “|” 放数组A,“[” 和 “]” 放数组B,数字字符转化为int类型后存入另一个数组C。

以给的输入样例作为例子:

在遍历到 “]" 的前一个字符时:

A:HG|B|CA

B:[[

C: 3 2

读取到 ”]" 时,先将B栈顶出栈,用temp记录A最右边的 ”|“之后的数据(即”CA”);

C栈顶出栈,记录出栈元素e,再把A最右边的 ”|“以及之后的数据全部删除,然后在A尾部添加 e个temp;

此时的各栈内容为:

A:HG|BCACA

B:[

C: 3

然后重复上述操作即可。




以下为代码实现:

#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

using namespace std;

string a,b,c,p;//a为输入字符串,b储存中括号,c储存字母及“|”
string temp;

int Find(int t)
{
    while(c[t]!='|')
    {
        t--;
    }
    return t;   //返回'|'的位置
}

int main()
{
    int i=-1,j=-1,k=-1,m=0,g[100000],g1=0,t;//g储存数字,g1储存g的下标,i/j/k分别对应a,b,c尾指针
    cin>>a;
    int code,len,x;
    len=a.length();                     //记录字符串长度(string字符串没有“\0”结束符)
    for(i=0; i<len; i++) //遍历字符串a
    {
        if(a[i]>='A'&&a[i]<='Z'||a[i]=='|') //入栈c
        {
            c+=a[i];
            ++k;
        }
        else if(a[i]=='[')      //入栈b
        {
            b+=a[i];
            ++j;
        }
        else if(a[i]==']')
        {
            if(b[j]=='[')
            {
                j--;  // '['出栈
                code=Find(k); //返回c中左边第一个‘|’的位置
                t=k-code;     //截取的数据个数
                temp=c.substr(code+1,t);  //从code+1位置开始截取c的t个字符
                c.erase(code,t+1);        //删除位置code及code之后的内容
                k=k-t;                     //更新尾指针
                for(g1--,m=0; m<g[g1]; m++) //对需要解压部分进行解压,即多次在c尾部添加temp
                {
                    c+=temp;
                    k=k+t;
                }
                g[g1]=0;
            }
        }
        else if(a[i]>='0'&&a[i]<='9')  //数字读入数组g
        {
            g[g1]=0;
            while(a[i]>='0'&&a[i]<='9')
                g[g1]=g[g1]*10+a[i++]-'0';
            i--;
            g1++;
        }
    }
    cout<<c<<endl;
    return 0;
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值