洛谷 P1928 外星密码
好久不见,随便找一题找找感觉。
递归写法:
#include<bits/stdc++.h>
using namespace std;
string s;
string times(string x,int cnt)
{
string newstr="";
while(cnt--) newstr+=x;
return newstr;
}
pair<string,int> decompress(int pos)
{
int num=0;
string temp="";
// printf("num=%d ",num);
// cout<<"s="<<s<<endl;
for(int i=pos;i<s.size();i++)
{
// printf("i=%d ",i);
// cout<<"temp="<<temp<<endl;
if(s[i]>='A' && s[i]<='Z') temp+=s[i];
else if(s[i]>='0'&&s[i]<='9') num=num*10+s[i]-'0';
else if(s[i]=='[')
{
pair<string,int> stock=decompress(i+1);
temp+=stock.first;
i=stock.second;
// printf("!i=%d\n",i);
// printf("num=%d\n",num);
// cout<<"temp="<<temp<<endl;
}
else if(s[i]==']')
{
// printf("num=%d ",num);
// cout<<"temp="<<temp<<endl;
return make_pair(times(temp,num),i);
}
}
}
int main()
{
cin>>s;s.insert(0,"1"),s.append("]");
cout<<decompress(0).first;
return 0;
}
栈实现模拟:
#include<bits/stdc++.h>
#define N 20005
using namespace std;
int n,sta[N],top;
string s,strsta[N];
string times(string x,int cnt)
{
string newstr="";
while(cnt--) newstr+=x;
return newstr;
}
int main()
{
cin>>s;
n=s.size();
int num=0;bool flag=false;
for(int i=0;i<n;i++)
{
// printf("i=%d top=%d\n",i,top);
if(s[i]>='0' && s[i]<='9') num=num*10+s[i]-'0';
else if(s[i]>='A' && s[i]<='Z')
{
if(flag) sta[++top]=num,num=0,flag=false;
strsta[top]+=s[i];
}
else if(s[i]==']')
{
string strtmp=strsta[top];int tmp=sta[top];
// printf("i=%d top=%d tmp=%d\n",i,top,tmp);
// cout<<"strtmp="<<strtmp<<endl;
strsta[top]="";//一定要清空,因为后面不是赋值而是累加
top--;
strsta[top]+=times(strtmp,tmp);
}
else if(s[i]=='[')
{
if(flag) sta[++top]=num,num=0;
flag=true;
}
}
cout<<strsta[0];
}
苯题括号嵌套,递归拆括号求解子问题是常见的写法,找到最基本问题:\([num(+chr)+...(+chr)]\),然后代码就好写了。
所以提示是以后对于此类递归题,找到子问题的形式大概是比较重要的。
递归本质上就是栈,所以栈的写法自然也是可行的。或者说我们需要栈这样一个后入先出的结构来存储先前已经跑完的信息,这样才能处理接下来的内容。
提供几组小样例:
\([1A][2B]\)
\(AC[3F[4A]T]\)
\(3F[4A[2[B]]]\)
\(2[2[2[B]]]\)