ACM-递归之展开字符串——hdu1274

展开字符串

Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other)

Problem Description
在纺织CAD系统开发过程中,经常会遇到纱线排列的问题。
该问题的描述是这样的:常用纱线的品种一般不会超过25种,所以分别可以用小写字母表示不同的纱线,例如:abc表示三根纱线的排列;重复可以用数字和括号表示,例如:2(abc)表示abcabc;1(a)=1a表示a;2ab表示aab;如果括号前面没有表示重复的数字出现,则就可认为是1被省略了,如:cd(abc)=cd1(abc)=cdabc;这种表示方法非常简单紧凑,也易于理解;但是计算机却不能理解。为了使计算机接受,就必须将简单紧凑的表达方式展开。某ACM队接受了此项任务。现在你就是该ACM队的一员,请你把这个程序编写完成。

已知条件:输入的简单紧凑表达方式的长度不超过250个字符;括号前表示重复的数不超过1000;不会出现除了数字、括号、小写字母以外的任何其他字符;不会出现括号不配对等错误的情况(错误处理已由ACM其他队员完成了)。


Input

本题有多个测试数据组,第一行输入的就是数据组数N,接着就是N行表达式,表达式是按照前面介绍的意义书写的。


Output

输出时含有N行,每行对应一个输入的表达式。


Sample Input
2
1(1a2b1(ab)1c)

3(ab2(4ab))


Sample Output
abbabc

abaaaabaaaababaaaabaaaababaaaabaaaab


这是一道递归的题目,抠的挺细的感觉,

要多注意题干,我刚开始交了,没看到 cd(abc)=cdabc

结果WA一次,下次看题真要仔细了。


方法当然是递归了,

刚开始分情况:

①碰到数字

②碰到字符

③碰到括号(左括号或者右括号)


碰到数字,也有可能是多位数字,比如12a,

我就用的就是一个变量,sz, 当遇到数字,sz=str[i]-'0'+sz*10

这样多少位都不怕了(当然要在整型范围内哈),


碰到字符,我是判断前一个(就是str[i-1])是不是数字,

如果是数字,那就在主串上加上,重复的相应字符,

如果不是数字,那就代表是1,直接加上这个字符就行了


碰到左括号,当然递归,这里有一点注意,括号内情况有多种:

1.   2(ab)

2.   (ab)

3.   (2ab)

4.   (a2b)

5.   (2ab3(..))

这几种情况,都要考虑一下,尤其是,碰到括号前如果不是数字。

我遇到括号,先判断括号前一个数字,是不是数字,如果不是数字,

那就将sz变量设置为1,这样当括号回来(递归结束),可以循环一次。


碰到右括号,右括号注意事项不多,一般,我的主函数中遇到就直接跳过,

递归函数遇到就return,


仔细一点,就很容易AC了。

代码:

#include <iostream>
#include <string>

using namespace std;
// str,len,i 都是全局变量
string str;
int len,i;

string tobracket(void)
{
	// str1 辅助串
	int j,sz=0;
	string str1="";

	for(;i<len;++i)
	{
		// 遇到数字
		if(str[i]>='0' && str[i]<='9')
		{
			sz=str[i]-'0'+sz*10;
		}
		// 遇到字符
		else if(str[i]>='a' && str[i]<='z')
		{
			if(str[i-1]>='0' && str[i-1]<='9')
			{
				for(j=0;j<sz;++j)
					str1+=str[i];
				sz=0;
				continue;
			}
			str1+=str[i];			
		}
		// 遇到左括号
		else if(str[i]=='(')
		{
			
			if(str[i-1]>='a' && str[i]<='z')	sz=1;
			++i;
			string str_bt=tobracket();
	
			for(j=0;j<sz;++j)
				str1+=str_bt;
			sz=0;
		}
		// 遇到右括号
		else
			return str1;
	}
}


int main()
{
	string str_final;
	int j,n,sz;

	cin>>n;
	while(n--)
	{
		cin>>str;
		len=str.length();
		sz=0;
		str_final="";

		for(i=0;i<len;++i)
		{
			// 遇到数字
			if(str[i]>='0' && str[i] <='9')
			{
				sz=str[i]-'0'+sz*10;
			}
			// 遇到字符
			else if(str[i]>='a' && str[i]<='z')
			{
				if(str[i-1]>='0' && str[i-1] <='9')
				{
					for(j=0;j<sz;++j)
						str_final+=str[i];
					sz=0;
					continue;
				}
				str_final+=str[i];
			}
			// 遇到左括号
			else if(str[i]=='(')
			{
				
				if(str[i-1]>='a' && str[i]<='z')	sz=1;
				++i;
				string str_bt=tobracket();
				
				for(j=0;j<sz;++j)
					str_final+=str_bt;
				sz=0;
			}			
		}
		cout<<str_final<<endl;
	}

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值