华师一附中OI组
标题:
P1928 外星密码
[打印本页]
作者:
admin
时间:
2018-5-5 18:57
标题:
P1928 外星密码
https://www.luogu.org/problemnew/show/P1928
题目描述
有了防护伞,并不能完全避免 2012 的灾难。地球防卫小队决定去求助外星种族的帮 助。经过很长时间的努力,小队终于收到了外星生命的回信。但是外星人发过来的却是一 串密码。只有解开密码,才能知道外星人给的准确回复。解开密码的第一道工序就是解压 缩密码,外星人对于连续的若干个相同的子串“X”会压缩为“[DX]”的形式(D 是一个整 数且 1≤D≤99),比如说字符串“CBCBCBCB”就压缩为“[4CB]”或者“[2[2CB]]”,类 似于后面这种压缩之后再压缩的称为二重压缩。如果是“[2[2[2CB]]]”则是三重的。现 在我们给你外星人发送的密码,请你对其进行解压缩。
输入输出格式
输入格式:
第一行:一个字符串
输出格式:
第一行:一个字符串
输入输出样例
输入样例#1:
AC[3FUN]
输出样例#1:
ACFUNFUNFUN
说明
【数据范围】
对于 50%的数据:解压后的字符串长度在 1000 以内,最多只有三重压缩。
对于 100%的数据:解压后的字符串长度在 20000 以内,最多只有十重压缩。 对于 100%的数据:保证只包含数字、大写字母、’[‘和’]‘
作者:
admin
时间:
2018-5-5 20:30
#include <iostream>
using namespace std;
string ms(string s)
{
///自左向右找第一个] 他的左边第一个就是对应的[ 要是没有找到] 说明无法分解
int i,j,k,l,x;
string t,tt;
i=s.find(']');
l=s.size();
if (i==-1) return s;
else
{
j=i;
while (s[j]!='[' && j>=0) j--;
if (j<0) return "ERROR!!!" ;///按照题意,这个应该不可能
k=j+1;
x=0;
while (s[k]>='0' && s[k]<='9')
{
x=10*x+s[k]-'0'; ///数字合成
k++;
}
tt=t="";
for (int kk=k; kk<=i-1; kk++) t=t+s[kk]; ///生成单串
for (int kk=1; kk<=x; kk++) tt=tt+t; ///生成重复
tt=s.substr(0,j)+tt+s.substr(i+1,l-i-1) ///合成展开串
return ms(tt);///递归
}
}
int main()
{
string s;cin>>s;
cout<<ms(s);
return 0;
}
复制代码
作者:
张笑宇
时间:
2018-5-5 20:57
#include<iostream>
using namespace std;
string s;
int l,sum,i,j,p[100];///sum个正括号,分别在p[i]
int num(int x)
{
int nn;
if (s[x+2]>='0' && s[x+2]<='9')
nn=(s[x+1]-'0')*10+(s[x+2]-'0');
else
nn=(s[x+1]-'0');
return nn;
}
string be(int x)
{
string bes="";
for (j=0;j<=x-1;j++) bes=bes+s[j];
return bes;
}
string he(int l,int r,int c)///左端点 右端点 重复次数
{
string her="",sher;///sher记录her
if (c<=9) l=l+2;
else l=l+3;
r--;
for (j=l;j<=r;j++) her=her+s[j];
sher=her;
for (j=1;j<=c-1;j++) her=her+sher;
return her;
}
string af(int l,int r)
{
string aft="";
for (j=l+1;j<=r;j++) aft=aft+s[j];
return aft;
}
int main()
{
cin>>s;
l=s.size(),sum=0;///sum括号的个数
for (i=0;i<=l-1;i++)
{
if (s[i]=='[') sum++,p[sum]=i;
}
for (i=sum;i>=1;i--)///从内向外扫
{
l=s.size();
int number=num(p[i]);///重复次数
string before=be(p[i]);///把该括号之前的串复制下来
int pp=p[i];
while (s[pp]!=']') pp++;///反括号在s[pp]
string here=he(p[i],pp,number);///在[]中的字符串
string after=af(pp,l);///在反括号之后的串
s=before+here+after;
}
cout<<s;
return 0;
}
复制代码
作者:
admin
时间:
2018-5-5 21:12
点评下楼上zxy同学的程序,感觉太过于随意。
1、截取字符串里面的一段有现成的函数
2、数字串合并成数字也有标准的做法
3、至于那个判断位置的那段,也有隐患
这三个地方或者用函数,或者应该用扫描算法,这需要大家的编程功底
作者:
黄煦喆
时间:
2018-5-5 21:13
#include<iostream>
using namespace std;
string s,ss,t;
int l,r,a;
string ms(string s)
{
r=s.find(']');
if(r==-1)return s;
r--;
l=r;
while(s[l]!='[')l--;
l++;
a=s[l]-'0';
l++;
if(s[l]>='0'&&s[l]<='9'){a=a*10+(s[l]-'0');l++;}
for(int j=l;j<=r;j++)t+=s[j];
for(int m=1;m<=a;m++)ss+=t;
ss=s.substr(0,l-2)+ss+s.substr(r+2,s.size()-r-1);
return ms(ss);
}
int main()
{
cin>>s;
cout<<ms(s);
return 0;
}
复制代码
这个同学t ss没有赋初值,肯定有问题!!!而且,变量最好专用,多设几个无所谓的,你看他的l r总在变,很容易糊涂的,这里有隐患
作者:
黄煦喆
时间:
2018-8-2 10:25
#include<iostream>
using namespace std;
string ts,ss,t;
int l,r,a;
string ms(string s)
{
a=0;
t=ss="";
r=s.find(']');
if(r==-1)return s;
int p=r;
l=r;
while(s[l]!='['&&l>=0)l--;
int q=l+1;
while(s[q]<='9'&&s[q]>='0')
{
a=10*a+(s[q]-'0');
q++;
}
for(int j=q; j<p; j++)t+=s[j];
for(int m=1; m<=a; m++)ss+=t;
ss=s.substr(0,l)+ss+s.substr(r+1);
return ms(ss);
}
int main()
{
cin>>ts;
cout<<ms(ts);
return 0;
}
复制代码
欢迎光临 华师一附中OI组 (http://hsyit.cn/)
Powered by Discuz! X3.2