单词记忆方法
模拟+栈
题目描述
牛牛考完了四六级,准备分享一下自己的英语学习方法。
牛牛:学习英语最重要的就是背单词,如果你能把所有的单词都记住,那么你的英语就能变成天下第一。
然而牛牛的记忆方法就是把单词的每个字母转换成数字,把A看成1,B看成2,C看成3A看成1,B看成2,C看成3{}A看成1,B看成2,C看成3,依次类推,然后计算出来这个单词每个字母的和。从此每次想到这个单词,就要先想到这个单词的和,然后想办法凑出这个和。
不久后,牛牛又对自己的记忆方法进行了更新,可以把重复的连续字母进行合并,
比如把ABCABC写成(ABC)2,HHHH写成(H2)2或者H4ABCABC写成(ABC)2,HHHH写成(H2)2或者H4{}ABCABC写成(ABC)2,HHHH写成(H2)2或者H4,这样计算和的时候只需要用里面的和乘个数就可以了,更加方便。(但是有时候牛牛由于老花眼没有发现几个相同的连续字母是重复的,所以导致他没进行合并)
现在到了牛牛考验你的时间了,牛牛告诉你一个单词,这个单词可能很长甚至你从来没见过,但牛牛要你按他的方法算出这个单词的和。
题目分析:这是一个稍微复杂的模拟题,但是只要细心写,每一步都判断一下,每一种情况都写一遍,那么还是可以写出来的,这种题目是第二次见了,第一次没写出来,第二次还是没写出来,我哭了~~
看了大佬的题目,实在是感叹,太精妙了,每一步写的有理有据,十分的通俗易懂也十分的好,具体看代码解析~
#include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; typedef long long ll; char c[maxn]; stack<ll> s1, s2, s3; //用来保存当前段内总数,数字,字母 int main() { scanf("%s", c); int lc = strlen(c); ll ans = 0, sum = 0, alp = 0; for (int i = 0; i < lc; ++i) { if (c[i] == '(') { //如果遇到左括号,那么把之前的信息入栈,并且清空,为后续做准备 s1.push(sum); s2.push(ans); s3.push(alp); sum = 0; ans = 0; alp = 0; } else if (c[i] == ')') { //如果遇到的是右括号,那么把当前值出栈 ll tmp = sum; //把当前括号内的数赋给一个临时变量 sum = s1.top(); s1.pop(); ans = s2.top(); s2.pop(); alp = s3.top(); s3.pop(); if (isdigit(c[i + 1])) //如果下一个是数字的话,那么直接加起之前的值,因为要乘以后序括号的值 alp += tmp; else sum += tmp; //否则就直接加在总数上面, } else if (isdigit(c[i])) { ans = ans * 10 + c[i] - '0'; //记录数字的大小 if (i + 1 == lc || !isdigit(c[i + 1])) { //如果下一个字符不是数字,那么直接加起来并且要乘以下标 sum += ans * alp; ans = 0; alp = 0; } } else { //如果是字母那么就计算一下就行 alp += c[i] - 'A' + 1; if (i + 1 == lc || !isdigit(c[i + 1])) { sum += alp; //直接加起来就行 alp = 0; } } } printf("%lld\n", sum); }