zoukankan      html  css  js  c++  java
  • ZOJ 2240. Run Length Encoding

        地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2240

        题意:对一个给定字符串,按照下面的方式编码,输出结果。

        (1)连续出现的数量在 2~9 个之间的字符,用两个字符表示。第一个字符表示数量(2~9),第二个是该字符。如果连续字符数量超过 9 个,先编码前 9 个字符,然后继续编码其余部分。

        (2)对于不包含连续字符的序列,先输出一个字符 1,然后是这个序列,然后结尾再追加一个字符 1。如果序列中包含字符 1,则在前面加一个转义字符 1,即输出连续两个 1。

        分析:粗看此题比较简单,线性扫描一次字符串即可。扫描过程涉及到状态转换,难度不大。但必须仔细阅读题目要求,因此需要很大的细心。我提交了 5 次才通过。主要是仔细审题。代码无须解释,严格按照题目要求的编码即可。只要通过基本测试即可。下面举几个典型的例子:

        aaaxyz -> 3a1xyz1

        aaa817 -> 3a181171

        aaaaaaaaaa -> 9a1a1

        11 -> 21

        1 -> 1111

        aaab -> 3a1b1

        下面是第 8 次提交的代码,主要变动是去掉了不必要的用于存储“不重复字符序列”的辅助空间,和一些细微调整(发现不重复序列的截止点时,直接转入重复序列状态,而不是未知状态。发现重复序列的截止点时,必须进入未知状态,因为下一个状态取决于 p[2] 和 p[1] 的关系)。把循环体内的 if - else if 改成了 switch 语句,以让逻辑更清楚。

    zoj2240_code
    #include <stdio.h>
    
    #define UNKNOW    0    /* 未知状态 */
    #define SUBSTR    1    /* 处于 不重复字符序列 中 */
    #define REPEAT    2    /* 处于 重复字符序列 中 */
    
    /* 输出不重复字符序列中的一个字符,1 需要转义 */
    void put_one_char(char c)
    {
        if(c == '1') printf("11");
        else putchar(c);
    }
    
    void encode(char* text)
    {
        char* p = text;
        int status = UNKNOW;
        int count; /* 重复字符序列长度 */
        while(*p)
        {
            switch(status)
            {
            case UNKNOW: /* 检测当前所处状态 */
                if(p[1] != p[0])
                {
                    status = SUBSTR;
                    printf("1"); /* 前缀 1 */
                    put_one_char(*p);
                }
                else
                {
                    status = REPEAT;
                    count = 1;
                }
                break;
    
            case SUBSTR: /* 位于 不重复字符序列 中 */
                if(p[1] != p[0])
                {
                    put_one_char(*p);
                }
                else
                {
                    printf("1"); /* 后缀 1 */
                    status = REPEAT;
                    count = 1;
                }
                break;
    
            case REPEAT: /* 位于 重复字符序列 中 */
                count++;
                if(count == 9 || p[1] != p[0])
                {
                    printf("%d%c", count, *p);
                    status = UNKNOW;
                }
                break;
            }
            ++p;
        }
    
        /* 重要:如果以不重复字符序列结束,循环结束后输出后缀 1 */
        if(status == SUBSTR) printf("1");
    }
    
    int main(int argc, char* argv[])
    {
        char line[1024];
        while(gets(line) != NULL)
        {
            encode(line);
            printf("\n");
        }
        return 0;
    }

        encode 函数中,由于前两个 case 的代码比较接近,因此可以把前两个 case 合并到一起,使代码更紧凑,但可读性可能有所降低。代码如下:

    code_encode_v2
    void encode(char* text)
    {
        char* p = text;
        int status = UNKNOW;
        int count; /* 重复字符序列长度 */
        while(*p)
        {
            switch(status)
            {
            case UNKNOW: /* 检测当前所处状态 */
            case SUBSTR: /* 位于 不重复字符序列 中 */
                if(p[1] != p[0])
                {
                    if(status == UNKNOW)
                    {
                        status = SUBSTR;
                        printf("1"); /* 前缀 1 */
                    }
                    put_one_char(*p);
                }
                else
                {
                    if(status == SUBSTR) printf("1"); /* 后缀 1 */
                    status = REPEAT;
                    count = 1;
                }
                break;
    
            case REPEAT: /* 位于 重复字符序列 中 */
                count++;
                if(count == 9 || p[1] != p[0])
                {
                    printf("%d%c", count, *p);
                    status = UNKNOW;
                }
                break;
            }
            ++p;
        }
    
        /* 重要:如果以不重复字符序列结束,循环结束后输出后缀 1 */
        if(status == SUBSTR) printf("1");
    }

        代码中需要注意的几点:

        (1)如果是连续出现的字符1,是不需要转义的,因为这时的 1 不会有歧义。例如“111” 被编码为“31”,而不是“311”。

        (2)如果字符串以不重复序列结束,则不要遗忘输出后缀 1。遇到字符串结尾时,循环结束,但序列可能尚未输出完成!这仅存在于字符串的最后一个字符和倒数第二个字符不同的情况(如果相同,则属于连续字符序列,在循环结束之前已经输出了)。

  • 相关阅读:
    CF763C Timofey and Remoduling
    CF762E Radio Stations
    CF762D Maximum Path
    CF763B Timofey and Rectangles
    URAL1696 Salary for Robots
    uva10884 Persephone
    LA4273 Post Offices
    SCU3037 Painting the Balls
    poj3375 Network Connection
    Golang zip压缩文件读写操作
  • 原文地址:https://www.cnblogs.com/hoodlum1980/p/2578342.html
Copyright © 2011-2022 走看看