【模拟】【栈】外星密码 password.pas/c/cpp

外星密码

Problem:       password.pas/c/cpp
Input:       password.in
Output:       password.out
Memory Limit:   128 MB
Time Limit:      1 sec

  【题目描述】

为了避免2012世界末日的灾难。地球防卫小队决定去求助外星种族的帮助。经过很长时间的努力,小队终于收到了外星生命的回信。但是外星人发过来的却是一串密码。只有解开密码,才能知道外星人给的准确回复。解开密码的第一道工序就是解压缩密码,外星人对于连续的若干个相同的子串“x”会压缩为“[DX]”的形式(D是一个整数且1≤D≤99),比如说字符串“CBCBCBCB”就压缩为“[4CB]”或者“[2[2CB]]”,类似于后面这种压缩之后再压缩的我们称之为二重压缩。如果是“[2[2[2CB]]]",则是三重。现在我们给你外星人发送的密码,请你对其进行解压缩。

【输入格式】

第1行:一个字符串

【输出格式】

第1行:一个字符串

【输入样例】

AC[3FUN]

【输出样例】

ACFUNFUNFUN

【数据范围】

  对于50%的数据:解压后的字符串长度在1,000以内,最多只有三重压缩。

  对于100%的数据:解压后的字符串长度在20,000以内,最多只有十重压缩。

  保证只包含数字、大写字母、‘[’和‘]’。

 

 

 

这一题显然把字符串操作考得淋漓尽致!很普通的模拟就可以了,不过代码量。。。。。。

我上午是用的栈维护,一个存数,一个存字符串(就是括号里面的字符串)

然后每读到'['的时候就读一个数,进栈,然后就读字符,一直读到'[' 或者 ']'的时候停下,并把字符串也压栈。

后面遇到']'的时候就弹出数栈和字符串栈进行复制加倍,最后输出

 

不过在实际操作中遇到了问题,比如下面这个例子 A[2A[2AB]A]         很显然应该输出 A | A ABAB A | A ABAB A  (空格和竖线是我自己加上的,便于观察)

那么我们模拟一遍上面的过程

 

步骤 数栈 字符串栈
定义字符串s最为答案用 <null> <null>
读到A,并且不再括号内,所以加入s,s现在为"A" <null> <null>
读到'[',然后读一个数2,压栈 2 <null>
一直读字符串,直到'['或']'停下,结果为A,压栈 2 A
刚才最后读到的为'[',所以读一个数字2,压栈

2
2

A
接着又读字符串,读到']'停止,结果为AB,压栈

2
2

AB
A
刚才最后读到']',所以弹出数栈和字符串栈进行加倍 2 A
加倍后变为ABAB,压栈 2

ABAB
A

接着读到字符串A压栈 2

A
ABAB
A

又读到']',弹出字符串栈和数栈加倍 <null> <null>
加倍为AABABAAABABA,压栈 <null> AABABAAABABA
读到文末,字符串栈弹出 <null> <null>
s加上字符串栈弹出的,输出 <null> <null>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

注意上面绿色字体的几个地方
①  :如何判断是否在括号里面呢?我们可以用区间的思想,用一个变量,遇到'['就+1,遇到']'就-1,那么当其值为0的时候就不在括号内
②③ :如何弹出,弹出几个呢?注意到第二处和第三处,如果不是手动维护,我们根本不知道到底要弹出几个,那该怎么办呢?一个有效的解决办法就是在数字压栈的时候同时把一个"["(或者其他可以区分的符号)也压入字符串栈,那为什么不在字符串入栈的时候压呢?因为字符串入栈的时候不一定是因为'['而入栈的。这样处理后,我们每次只需一直弹出字符串栈,直到弹出的是"["为止。

还有一个需要注意的问题就是弹出的时候,要注意字符串拼接相加的顺序,后出栈的要加在前面(可以自己模拟一次),才能保证不改变原来顺序

剩下的上代码

C++ Code

/*
C++ Code
http://oijzh.cnblogs.com
By jiangzh
*/
#include<cstdio>
#include<cctype>
#include<stack>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;

string s;
stack<int> nu;
stack<string> alp;
int co=0;

void work()
{
    freopen("password.in","r",stdin);
    freopen("password.out","w",stdout);
    char ch;
    int x;
    while(scanf("%c",&ch)==1)
    {
        if(ch=='\n') break;//只读第一行
        if(co>0)
            {
                string ss="";
                while(ch!=']' && ch!='[')
                {
                    ss+=ch;
                    scanf("%c",&ch);
                }
                alp.push(ss);
            }

        if(ch=='[')
        {
            co++;
            scanf("%d",&x);
            nu.push(x);
            alp.push("[");
        }

         if(ch==']')
            {
                co--;
                x=nu.top();nu.pop();
                string t="";
                while(!alp.empty())
                {
                    string ss=alp.top();
                    alp.pop();
                    if(ss=="[") break;
                    t=ss+t;
                }
                string tt=t; t="";
                for(int i=1;i<=x;i++) t=t+tt;
                alp.push(t);
            }
        if(co<=0)
            while(!alp.empty())
            {
                if(alp.top()!="[") s+=alp.top();
                alp.pop();
            }
        if(ch!='[' && ch!=']') s+=ch;
        ch='@';
    }
    cout<<s;
    while(!alp.empty())
    {
        cout<<alp.top();
        alp.pop();
    }
    printf("\n");
}

int main()
{
    work();
    return 0;
}

  

 

posted @ 2012-11-06 13:22  jiangzh  阅读(518)  评论(0编辑  收藏  举报