【hdu1274】展开字符串(栈操作)


展开字符串

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2969    Accepted Submission(s): 1459


Problem Description
在纺织CAD系统开发过程中,经常会遇到纱线排列的问题。
该问题的描述是这样的:常用纱线的品种一般不会超过25种,所以分别可以用小写字母表示不同的纱线,例如:abc表示三根纱线的排列;重复可以用数字和括号表示,例如:2(abc)表示abcabc;1(a)=1a表示a;2ab表示aab;如果括号前面没有表示重复的数字出现,则就可认为是1被省略了,如:cd(abc)=cd1(abc)=cdabc;这种表示方法非常简单紧凑,也易于理解;但是计算机却不能理解。为了使计算机接受,就必须将简单紧凑的表达方式展开。某ACM队接受了此项任务。现在你就是该ACM队的一员,请你把这个程序编写完成。
已知条件:输入的简单紧凑表达方式的长度不超过250个字符;括号前表示重复的数不超过1000;不会出现除了数字、括号、小写字母以外的任何其他字符;不会出现括号不配对等错误的情况(错误处理已由ACM其他队员完成了)。
 

Input
本题有多个测试数据组,第一行输入的就是数据组数N,接着就是N行表达式,表达式是按照前面介绍的意义书写的。
 

Output
输出时含有N行,每行对应一个输入的表达式。
 

Sample Input
 
     
21(1a2b1(ab)1c)3(ab2(4ab))
 
Sample Output
 
     
abbabcabaaaabaaaababaaaabaaaababaaaabaaaab
 

Author
Cai Minglun
 

Source
 

Recommend
lcy   |   We have carefully selected several similar problems for you:   1276  1880  1106  1201  1075 

题意:给你一个字符串,根据前面的数字来展开输出。

分析:该题的难点在于对于字符串中的括号进行处理,由于许多括号有包含关系,所以首先能想到的就是利用递归,不过当时自己想递归的时候各种绕,所以换成了栈来实现orz。。。。还有一点就是杭电的数据貌似有点水,虽然题面上说数字不超过1000,但是最开始写的时候仅仅考虑了一位数的情况也ac了,所以数字的范围应该只有10以内的数。



#include <bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    string a;
    //freopen("in.txt","r",stdin);
    //freopen("myout.txt","w",stdout);
    int cas = 0;
    stack<char>s;
    while(~scanf("%d",&t))
    {
        while(t--)
        {

            cin>>a;
            for(int i = 0; i < a.length(); i++)
            {
                if(a[i] == '('||(a[i] <= '9'&&a[i] >= '0'))
                    s.push(a[i]);
                else if(a[i] <= 'z'&&a[i] >= 'a')
                {
                    if(s.top() <= '9'&&s.top() >= '0')
                    {
                        int n = 0;
                        int num[10], k = 0;
                        while(s.top()<='9'&&s.top()>='0')//进行多位数字的确认
                        {
                            num[++k] = s.top()-'0';
                            s.pop();
                            if(s.empty())   break;
                        }
                        for(int x = k; x >= 1; x--)
                            n = n*10+num[x];//由于栈是先进后出,所以要倒过来算
                        while(n--)
                            s.push(a[i]);
			//亲测,这一部分就算换成(n = s[i].top()-'0'并且栈为空、字母前面没有数字等情况n直接赋值成1)也能ac,所以数据里应该没有10以上的数。
                    }
                    else s.push(a[i]);
                }
                else if(a[i] == ')')
                {
                    string ss = "";
                    while(s.top() != '(')
                    {
                        ss.insert(ss.begin(),s.top());
                        s.pop();
                    }
                    s.pop();
                    int n;
                    if(s.empty()||!(s.top()<='9'&&s.top()>='0'))   n = 1;
                    else
                    {
                        n = 0;
                        int num[10], k = 0;
                        while(s.top()<='9'&&s.top()>='0')//如上
                        {
                            num[++k] = s.top()-'0';
                            s.pop();
                            if(s.empty())   break;
                        }
                        for(int x = k; x >= 1; x--)
                            n = n*10+num[x];
                    }
                    while(n--)
                    {
                        for(int j = 0; j < ss.length(); j++)
                            s.push(ss[j]);
                    }
                }
            }
            string ans = "";
            while(!s.empty())//将栈里所有的数都压进ans里。
            {
                ans.insert(ans.begin(),s.top());
                s.pop();
            }
            cout<<ans<<endl;
            a.clear();
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值