腾讯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;
}