OJ:https://cn.vjudge.net/problem/HDU-1274
题目没什么好说的,只有两个注意点 ab(ab) = ab1(ab) 数字不大于1000,也就是说数字可能不止一位。
解析:
要将给定的字符串进行展开,直接进行展开就可以了,只是要注意存在几种情况
1.当前字符是数字的时候,将当前的数字n计算出来,接下来又分两种情况
1.数字后面直接跟的是一个字母,那么直接将后面的字母循环n次输出就可以了
2.数字后面是一个括号,我们就要找出该左括号对应的右括号,然后将括号内的内容循环输出n次即可
2.当前字符是括号,当前直接出现括号,括号没有跟在数字后面,说明该括号内的内容输出一次即可
3.当前字符是数字,直接输出。
对于下面给出的代码,其实还有优化的空间,但是这个代码提交到oj上没有超时所以也就没有进行优化。
这里简单的讲解思路,代码中对于一个括号内重复输出n次,每次我们都是直接再次进行递归,其实可以将一次递归结果缓存起来,后面的n-1次就直接重复第一个递归的结果,就不用每次都去进行递归了。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 300
int isDigit(char c);
int stack[MAX];
int size;
void solve(char *s,int ss,int end,int *kk){
if(ss > end){
return;
}
for(int i=ss;i<=end;i++){
if(isDigit(s[i])){
int n = 0;
for(;i<=end;i++){
if(isDigit(s[i])){
n = n * 10 + s[i] - '0';
}else{
break;
}
}
if(s[i] == '('){
int e = kk[i];
for(int k=0;k<n;k++){
solve(s,i+1,e-1,kk);
}
i = e;
}else{
for(int k=0;k<n;k++){
printf("%c",s[i]);
}
}
}else if(s[i] == '('){
int r = kk[i]-1;
solve(s,i+1,r,kk);
i = r+1;
}else{
printf("%c",s[i]);
}
}
}
// 栈
void push(int c){
stack[size++] = c;
}
int pop(){
return stack[--size];
}
int isDigit(char c){
if(c >= '0' && c <= '9'){
return 1;
}
return 0;
}
int main()
{
int size=0;
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
char in[MAX];
// 记录每一个左括号对应的右括号的下标
int k[MAX];
scanf("%s",in);
int len = strlen(in);
// 利用栈求出每一个左括号对应的右括号的位置
for(int j=0;j<len;j++){
if(in[j] == '('){
push(j);
}else if(in[j] == ')'){
int l = pop();
k[l] = j;
}
}
solve(in,0,len-1,k);
printf("\n");
}
return 0;
}