题目2 : Best Compression Algorithms

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB

描述

易信是由网易和电信联合开发的一款即时通讯软件。除了语音聊天,免费电话等新功能以外,传统的文字信息聊天功能也得以保留,因此每天都有大量的文字信息需要在服务器中存储,中转。

小Y是一名负责处理文字信息的易信工程师,每天他都要和字符串打交道。为了提高存储和传输效率,小Y在课余时间经常会去研究字符串的存储方法。通过内部使用的一种统一的加密算法,所有的文字信息首先都会被转化成只包含大写字母['A'...'Z']的字符串。为了压缩这个加密后的字符串,小Y最近想出了两个存储的规则:

(1)如果字符串中有连续相同的大写字母,它们可以选择用"字符+出现次数"的方式替代。如字符串'AABCCCCDD',可以用'A2BC4D2'表示,也可以用'A2BC2C2DD'表示。

(2)如果字符串中有连续出现的模式串(模式串长度大于1),它们可以选择用"(模式)+出现次数"的方式替代。如字符串'FABCABCABCE',可以用'F(ABC)3E'表示,也可以用'F(ABC)2ABCE'表示。

上述规则中的"连续"均指出现次数大于1,规则(2)中的括号后一定是一个大于1的数值,代表出现次数。

综合上述两个规则,字符串'AABAABFAABAABFG'可以用'((A2B)2F)2G'表示。小Y保证输出的压缩串符合上述的两个规则,以下类型的非法字符串不会出现:

'(A)5': 括号冗余

'A1A4': 数字1冗余

'A((AA))2': 括号冗余

(ABC)1: 括号和数字1冗余

对于给定的一个用上述规则压缩后的字符串,对应的原串是唯一的。小Y想知道这个字符串原来的长度是多少,以此计算压缩倍率。你能帮助他吗?

输入

第一行是整数T(T <= 100),表示下面有T组数据。之后T行,每行为一组数据,每组数据为一个字符串。

每个字符串只会包含26个大写字母['A'...'Z'],数字['0'...'9']和左右括号['(', ')']。

保证输入数据一定合法,括号内的模式串长度一定大于1,表示出现次数的数字一定大于1,且字符串长度L <= 100。

输出

输出T行,每行对应一个数据的输出结果,表示字符串的实际长度。

保证每个字符串展开后的长度不超过109

样例输入
4
(AA)2A
((A2B)2)2G
WANGYI
A2BC4D2
样例输出
5
13
6
9

#include<iostream>

#include<stack>

using namespace std;

int power(int n)//10^n的值

{

    int sum = 1;

    for (int i = 0; i < n; i++)

    {

       sum *= 10;

    }

    return sum;

}

 

intresolver(char *&ch)//解析字符串中的数字

{

    stack<int>rs;

    int sum = 0, i = 0;

    while (*ch != '\0'&&*ch >= '0'&&*ch <= '9')

    {

       rs.push(*ch - '0');

       ch++;

    }

    ch--;

    while (rs.size() > 0)

    {

       sum += rs.top()*power(i++);

       rs.pop();

    }

    return sum;

}

int main()

{

    int n, r0, r1, po;

    char ch[101], *p;

    bool isleft = false, hasnum;

    stack<char>tmp;//使用栈来处理括号中的内容

    cin >> n;

    while (n-- > 0)

    {

       cin >> ch;

       p = ch;

       r1 = 0;

       r0 = 0;

       while (*p != '\0')

       {

           if (*p == '(')//若是左括号,则设标记位,并将字符入栈

           {

              isleft = true;

              tmp.push(*p);

           }

           else if (*p == ')')//若遇到右括号,则停止入栈,并处理最靠近栈顶的左括号的内容

           {

              po = 0;

              hasnum = false;

              while (tmp.size() > 0&& tmp.top() != '(')

              {

                  if (tmp.top() >= 'A'&&tmp.top()<= 'Z')

                  {

                     r0++;

                     tmp.pop();//对每个处理完的字符出栈

                     po = 0;

                  }

                  else if (tmp.top() >= '0'&&tmp.top()<= '9')

                  {

                     hasnum = true;

                     r0 += (tmp.top()- '0')*power(po++);

                     tmp.pop();

                  }

              }

              if (hasnum)r0--;

              tmp.pop();

              if (tmp.empty())

              {

                  p++;

                  r1 +=r0*resolver(p);

                  r0 = 0;

                  isleft = false;

              }

              else

              {

                  p++;

                  r0 =r0*resolver(p);

              }

           }

           else

           {

              if(isleft)tmp.push(*p);

              else//若字符不在括号范围内,则不入栈,直接处理

              {

                  if (*p >= 'A'&&*p <= 'Z')

                  {

                     r1++;

                  }

                  else

                  {

                     r1 +=resolver(p) - 1;

                  }

              }

           }

           p++;

       }

       cout << r1 <<endl;

    }

    return 0;

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值