题目描述
Given an expression s includes numbers, letters and brackets. Number represents the number of repetitions inside the brackets(can be a string or another expression).Please expand expression to be a string.
测试数据
s = abc3[a] return abcaaa
s = 3[abc] return abcabcabc
s = 4[ac]dy, return acacacacdy
s = 3[2[ad]3[pf]]xyz, return adadpfpfpfadadpfpfpfadadpfpfpfxyz
解题思路
很明显运算过程中具有嵌套的性质,需要使用栈来解决,又因为问题可分解,即将一个大的字符串看做S = C + (N[S])* + C
,其中C表示常量字符串,即在本层次不需要扩展的字符串,N表示数字,S表示待处理的字符串,*表示后面的部分可以多次出现。这样我们就可以通过递归来解决。
在使用递归的时候,对于C部分,直接加到结果中就行,问题在于中间的部分,即N[S]可能会出现多次,因此需要使用一个大循环,在循环中再递归。
另外,由于使用C语言实现,而C中并没有字符串这种数据类型,在返回结果的时候如果返回指针也不可以,因为函数返回的时候auto变量会被释放,所以需要自己定义一个字符串类型用于返回。
最后一个问题是对于原始字符串的遍历,需要在多层次的递归函数中保持指针位置的统一,所以使用了二重指针,这样就可以让不同层次的函数使用同一个指针进行操作。
C实现代码
#include <stdio.h>
typedef struct string
{
char data[100];
int length;
} string;
string expression_expand(char **src)
{
int num = 0;
string single, repeat;//single表示未重复的字符串,repeat表示已经重复处理的字符串
single.length = 0;
repeat.length = 0;
while(**src != '\0')
{
//首先将字符串中无需重复的部分取出
while(**src >= 'a' && **src <= 'z' && **src != '\0')
{
repeat.data[repeat.length++] = **src;
(*src)++;
}
//如果是数字,将数字提取出来
while(**src >= '0' && **src <= '9' && **src != '\0')
{
num *= 10;
num += **src - '0';
(*src)++;
}
//如果遇到'[',把后面字符串的重复工作交给下次递归处理
if(**src == '[')
{
(*src)++;
single = expression_expand(src);
}
//当获得数字后面的字符串的处理结果之后,
//由本次递归对整个结果进行重复处理
while(num != 0)
{
num--;
int i;
for(i = 0; i < single.length; i++)
{
repeat.data[repeat.length++] = single.data[i];
}
}
//如果遇到']',说明待重复的字符串已经提取完毕,返回给上层递归
if(**src == ']')
{
(*src)++;
return repeat;
}
}
return repeat;
}
int main(int argc, char *argv[])
{
char data[100];
char *point;
while(~scanf("%s", data))
{
point = data;
string ret = expression_expand(&point);
ret.data[ret.length] = '\0';
printf("%s\n", ret.data);
}
return 0;
}