题目链接
https://ac.nowcoder.com/acm/contest/7412/C
解题思路
递归匹配呗,反正我不会!WTCL!WTCL!WTCL!!!请骂我!!!
难就难在实现上,方法谁都懂,就是实现不出来!
AC代码1
我感觉代码1比代码2好理解,但是比代码2难自己实现。
#include<bits/stdc++.h> #define ll long long using namespace std; int i=0;//i要全局 string s; ll solve(){ ll res=0,a=0; for(;i<s.size();i++){ ll tmp=0; while(isdigit(s[i])) tmp=tmp*10+(s[i++]-'0'); res+=a*max(tmp,1LL); a=0; /* 不知道你能不能理解为什么循环找数字。 其实不是先循环找数字,而是每次找的数字都是上一个solve到的右括号后的数字。 比如(HHH)444,第一次从主函数进入slove,因为没有数字,所以第一个solve里的while循环进行不了; 匹配到左括号,进入从主函数的solve中进入solve函数; 这次进入solve依旧没法进入while,但是a存下了HHH的和,匹配到右括号break,返回到上一层的solve中,此时a依旧存的是HHH的和吧; 匹配到数字了,终于进入while了,tmp存下了444,再用a与tmp相乘,就是HHH的和与444相乘,得到了要的结果res。 所以,能看出什么呢?res的刷新用的是上一层solve中得到的a的值,对于本层solve就得直接用a去乘数字了,所以本层中要先去找数字相乘再进行别的操作。 */ if(isalpha(s[i])) a+=s[i]-'A'+1; if(s[i]=='(') i++,a=solve();//i++,跳过左括号并进入solve else if(s[i]==')') break; } res+=a;//万一字符串存在后缀字母,就加上 return res; } int main(){ cin>>s; cout<<solve()<<endl; }
AC代码2
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=1e5+10; int pos[N]; stack<int> stk; string s; ll solve(int l,int r){ ll res=0,num=0; for(int i=l;i<=r;i++){ if(s[i]=='('){//( ll tmp=solve(i+1,pos[i]-1); i=pos[i]+1; while(i<=r && isdigit(s[i])) num=num*10+(s[i++]-'0'); res+=tmp*max(num,1LL); num=0; i--; } else { if(i+1<=r && isdigit(s[i+1])){//i必然不是右括号,因为右括号是循环的右边界;如果i不是左括号,且i+1是十进制数,那么i必然是字母,因为如果i不是字母怎么会出现数字。总而言之,这个判断说明i为字母,i以后为若干数字 int x=i+1; while(x<=r && isdigit(s[x])) num=num*10+(s[x++]-'0'); res+=num*(s[i]-'A'+1); i=x-1; num=0; } else res+=s[i]-'A'+1;//i是字母,且i+1也是字母,即i以后存在若干个字母 } } return res; } int main(){ cin>>s; int n=s.length(); s='.'+s; for(int i=1;i<=n;i++){ if(s[i]=='(') stk.push(i); else if(s[i]==')') pos[stk.top()]=i,stk.pop();//左右括号匹配一下,pos[左括号的位置]=与之匹配的左括号的位置 } cout<<solve(1,n)<<endl; }