单词记忆方法

链接:https://ac.nowcoder.com/acm/contest/11334/C
来源:牛客网

题目描述
牛牛考完了四六级,准备分享一下自己的英语学习方法。

牛牛:学习英语最重要的就是背单词,如果你能把所有的单词都记住,那么你的英语就能变成天下第一。

然而牛牛的记忆方法就是把单词的每个字母转换成数字,把A看成1,B看成2,C看成3{}A看成1,B看成2,C看成3,依次类推,然后计算出来这个单词每个字母的和。从此每次想到这个单词,就要先想到这个单词的和,然后想办法凑出这个和。

不久后,牛牛又对自己的记忆方法进行了更新,可以把重复的连续字母进行合并,

比如把ABCABC写成(ABC)2,HHHH写成(H2)2或者H4{}ABCABC写成(ABC)2,HHHH写成(H2)2或者H4,这样计算和的时候只需要用里面的和乘个数就可以了,更加方便。(但是有时候牛牛由于老花眼没有发现几个相同的连续字母是重复的,所以导致他没进行合并)

现在到了牛牛考验你的时间了,牛牛告诉你一个单词,这个单词可能很长甚至你从来没见过,但牛牛要你按他的方法算出这个单词的和。

输入描述:
输入仅有一行,表示牛牛给你的这个单词S{}输入仅有一行,表示牛牛给你的这个单词S
|S|<=10^5∣S∣<=10
5

S中只包含大写字母,左右括号以及数字,不包含其他字符{}S中只包含大写字母,左右括号以及数字,不包含其他字符

输出描述:
输出一行,表示这个单词的和{}输出一行,表示这个单词的和
保证这个和不大于10^{14}保证这个和不大于10
14

示例1
输入
复制
(A2B2)2
输出
复制
12
备注:
括号可能会嵌套出现
括号或者字母后面的数字也可能不止一位数,也可能没有数字,没有数字就表示为出现1次,但是这个数不可能为0

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 100;
#define LL long long
int pos[N],st[N],top,n;
char ch[N];
LL solve(int l,int r) {
    
    
    LL tot = 0;
//    cout << l << " " << r << endl;
    for(int i = l;i <= r;) {
    
    
        if(pos[i]) {
    
    
            LL res = solve(i + 1,pos[i] - 1);
            i = pos[i] + 1;
            LL x = 0;
            while(i <= r && isdigit(ch[i]))
            x = x * 10 + ch[i] - '0',i++;
            if(x) tot += res * x;
            else tot += res;
        }
        else {
    
    
            if(i + 1 <= r && isdigit(ch[i + 1]))
            {
    
    
                LL x = 0,old = i;i = i + 1;
                while(i <= r && isdigit(ch[i])) 
                x = x * 10 + ch[i] - '0',i++;
                tot +=  x * (ch[old] - 'A' + 1);
            }
            else tot += ch[i] - 'A' + 1,i++;
        }
    }
    return tot;
}
int main() {
    
    
    scanf("%s",ch+1);
    n = strlen(ch+1);
    for(int i = 1;i <= n;i++) {
    
    
        if(ch[i] == '(') st[++top] = i;
        if(ch[i] == ')') {
    
    pos[st[top]] = i;top--;}
    }
    cout << solve(1,n) << endl;
}

猜你喜欢

转载自blog.csdn.net/qq_45772483/article/details/112563307