-
描述
易信是由网易和电信联合开发的一款即时通讯软件。除了语音聊天,免费电话等新功能以外,传统的文字信息聊天功能也得以保留,因此每天都有大量的文字信息需要在服务器中存储,中转。
小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 "stdio.h" #include <iostream> #include <string> #include <stack> using namespace std; int pow( int n) { int result =1; if (n == 0) { return 1 ; } else { for ( int i = 0 ; i < n; ++i ) { result *= 10 ; } } return result ; } int main() { int n; string str; cin >> n ; while (n--) { cin >> str; stack <char> stack1; stack <char> stack2; bool isleft = false; bool isbacket = false; int result = 0; for ( int i = 0 ; i < str.length (); ++ i) { if ( str[i ] == '(' ) { isleft = true ; stack1 .push( str[i ]); } else if (str[i ]==')') { int multi = 1; int count = 0; bool hasnum=false; while ( stack1.size () > 0 && stack1.top ()!= '(' ) { if ( stack1.top () >= '0' && stack1.top () <= '9' ) { multi += ( stack1.top () - '0' ) * pow(count ) - 1; count ++; hasnum = true ; stack1 .pop(); } else if (stack1.top () >= 'A' && stack1.top () <= 'Z' ) { if ( hasnum) { result += multi; multi = 1 ; count = 0 ; hasnum = false ; } else { result ++; } stack1 .pop(); } } if ( isbacket&& hasnum && stack1.top() == '(' ) { result *= multi; isbacket = false ; hasnum = false ; } stack1 .pop(); if ( stack1.empty ()) { isleft = false ; } } else { int multi = 1; int count = 0; bool hasnum = false; if ( isleft) { if ( str[i ] >= '0' && str[i ] <= '9' && str[i - 1 ] == ')') { isbacket = true ; } stack1 .push( str[i ]); } else if (str[i ]>= '0' && str[i ] <= '9') { if ( str[i -1] == ')'&& isbacket == false) { isbacket = true ; } stack2 .push( str[i ]); if (( str[i +1]>= 'A' && str[i +1]<= 'Z')|| str [i+ 1] == '\0') { while (! stack2.empty ()) { multi += ( stack2.top () - '0' )* pow( count) -1; count ++; stack2 .pop(); } } if ( isbacket) { result = multi* result; isbacket = false ; } else { result += multi; hasnum = true ; } } else if (str[i ] >= 'A' && str[i ] <= 'Z' ) { isbacket = false ; result ++; } if ( hasnum) { result --; } } } cout << result << endl; } }