前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >字符串展开(递归)- HDU 1274

字符串展开(递归)- HDU 1274

作者头像
ACM算法日常
发布2018-08-07 19:38:19
5540
发布2018-08-07 19:38:19
举报
文章被收录于专栏:ACM算法日常

Problem Description

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

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

Input

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

Output

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

Sample Input

2

1(1a2b1(ab)1c)

3(ab2(4ab))

Sample Output

abbabc

abaaaabaaaababaaaabaaaababaaaabaaaab

关于递归:

递归是比较难于理解的,但又是一种重要的思想。如果一个问题可以转化成一个结构相同,规模更小的问题,则可以通过递归来解决。

递归是一种分析方法,可以帮助我们看清楚事物的本质。

如果确定了用递归法解题,思考的重点应该放到建立原问题和子问题之间的联系上面。

本题中对于左括号的出现就是递归方法运用的契机。而右括号出现后需要将当前位置返回给父函数则是父子函数间的纽带。

解题思路

数据量并不大,我们只需模拟即可,分两种策略

step1 : 如果是数字, 代表需要循环输出, 此时又分两种策略

1:如果后面是“(”, 则需要循环一个字符串, 即递归即可

2:如果后面是单个字母, 只需把后面的一个字母循环输出多次即可

step2:如果是字母, 直接输出

也就是说我们写的函数就是要输出后面字符串需要的次数,如果碰到了数字, 我们循环几次这个函数即可, 这就需要我们知道从哪个地方开始输出, 而且这个函数结束之后我们要知道已经进行到哪里了。因为后面的循环了之后,不需要再找了, 已经循环输出了。

本题解法的目标除了完成功能,还要求只允许一次字符串指针遍历,不使用strlen和strcpy之类的字符串函数,不使用额外数组,性能极优。

请看源码仔细体会。

源代码:G++ 0ms

代码语言:javascript
复制
#include <stdio.h>

//便于可读性写成函数,实际比赛使用宏
//是否是数字
int is_digit(char c) {
    return c >= '0' && c <= '9';
}

//是否是字母
int is_alpha(char c)
{
    return c >= 'a' && c <= 'z';
}

//解析字符串
//注意返回值是解析完成后字符串的位置
/*
思路:
1、一次遍历解决问题,仅使用自增操作进行遍历
2、做题前先思考如何规划问题的情况
本题中,对于字符串:1(1a2b1(ab)1c(ab))
我们先将数字抽象为符号D,字母抽象为符号s,那么指针在移动的时候会遇到4中情况,
分别是:
D(
s
Ds
s(
*/
char * parse(char * s)
{
    char * p = s;

    //特殊情况处理
    if (*p == 0 || *p == ')') {
        return p;
    }

    //每次前进一个位置
    for (p = s; *p; p++) {
        if (*p == ')') {
            return p;
        }
        //情况1、s
        if (is_alpha(*p)) {
            printf("%c", *p);
            continue;
        }

        int D = 0;
        while (is_digit(*p)) {
            D = D * 10 + (*p - '0');
            p++;
        }
        //情况4、s(
        D = D ? D : 1;

        if (*p == '(') {
            //情况2 D(
            char * n = 0;
            //输出n次
            for (int i = 0; i < D; ++i) {
                n = parse(p + 1);
            }
            //记得返回最后的位置
            p = n;
        } else {
            //情况3 Ds
            for (int i = 0; i < D; ++i) {
                printf("%c", *p);
            }
        }
    }
}

int main()
{
    int n = 0;
    char s[251];
    scanf("%d", &n);

    while (n--) {
        scanf("%s", s);
        parse(s);
        printf("\n");
    }

    return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-01-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ACM算法日常 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档