您的位置:首页 > 其它

ZOJ 2240. Run Length Encoding

2012-07-05 19:44 316 查看
    地址: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 语句,以让逻辑更清楚。

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。遇到字符串结尾时,循环结束,但序列可能尚未输出完成!这仅存在于字符串的最后一个字符和倒数第二个字符不同的情况(如果相同,则属于连续字符序列,在循环结束之前已经输出了)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: