博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ZOJ 2240. Run Length Encoding
阅读量:5911 次
发布时间:2019-06-19

本文共 3365 字,大约阅读时间需要 11 分钟。

    地址:

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

    (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 
#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。遇到字符串结尾时,循环结束,但序列可能尚未输出完成!这仅存在于字符串的最后一个字符和倒数第二个字符不同的情况(如果相同,则属于连续字符序列,在循环结束之前已经输出了)。

转载地址:http://twmpx.baihongyu.com/

你可能感兴趣的文章
【动态规划】The least round way
查看>>
如何统计序列中元素的出现频度
查看>>
流程(上)
查看>>
基于django的生成二维码的接口
查看>>
常识性概念
查看>>
java 集合框架(四)Set
查看>>
微信公众号支付 当前url未注册
查看>>
String类的常用方法详解
查看>>
通过Adobe Encode CC 2017,将一张静态图生成一个长时间的视频。
查看>>
git stash -- common usage
查看>>
rpm常用操作
查看>>
【LINUX】启用ssh服务
查看>>
pycharm2016序列号失效问题解决办法
查看>>
微软职位内部推荐-Senior Software Engineer
查看>>
详解MathType中如何更改公式颜色
查看>>
如何使用ABBYY FineReader 12将JPEG文件转换成可编辑文本
查看>>
JavaScript倒计时类
查看>>
第八周作业
查看>>
将Sublime Text 2搭建成一个好用的IDE(转)
查看>>
Intersection of Two Linked Lists(链表)
查看>>