可以使用直线语法压缩某些类型的数据,例如人工文本或源代码。您基本上可以创建一个语法,该语法的语言中只有一个词-未压缩的数据。在此任务中,您必须编写一个实现此数据压缩方法的程序。
输入项
输入的字符串长度不超过65535字节。确保输入匹配正则表达式[!-~]+
(即,至少一个可打印的ASCII字符,不包括空格)。
输入示例
abcabcbcbcabcacacabcabab
输出量
输出是形成规则的一组规则,这些规则描述了一个单词(输入)。每个非终结符均用大于9的十进制数表示。起始符号为符号编号十。下面给出了与示例输入相对应的示例输出;其语法在下面进一步描述:
10=11 11 12 12 11 13 13 11 14 14
11=a 12
12=b c
13=a c
14=a b
每个规则的形式<nonterminal>=<symbol> <symbol> ...
在右侧带有任意空格分隔的符号数。每个遵循以下限制并精确导出输入字符串的输出均有效。
限制条件
为了阻止人们做奇怪的事情,我们采取了许多限制措施:
每个非终结符必须在规则的右侧至少出现两次。例如,以下输入语法
abcabc
不合法,因为规则12仅出现一次:10=12 11=a b c 12=11 11
两个相邻符号的序列在所有规则的所有右侧都不能出现多次,除非它们重叠。例如,
abcabcbc
由于顺序bc
出现两次,因此以下输入语法无效:10=11 11 b c 11=a b c
有效的语法为:
10=11 11 12 11=a 12 12=b c
对于每个不超过65535字节的有效输入,您的程序必须在不到一分钟的时间内终止。
与往常一样,您不得使用任何语言功能或任何使解决方案变得微不足道或实现很大一部分的库函数。
样品输入
使用以下C程序生成样本输入。
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
unsigned int i,j = 0,k;
if (argc != 3
|| 2 != sscanf(argv[1],"%u",&i)
+ sscanf(argv[2],"%u",&k)) {
fprintf(stderr,"Usage: %s seed length\n",argv[0]);
return EXIT_FAILURE;
}
srand(i);
while(j < k) {
i = rand() & 0x7f;
if (i > 34 && i != 127) j++, putchar(i);
}
return EXIT_SUCCESS;
}
上面程序生成的样本输入通常不会产生良好的压缩结果。考虑使用人工文本或源代码作为示例输入。
获奖标准
这是代码高尔夫;源代码最短的程序为准。为了获得额外的荣誉,编写一个从输出中重构输入的程序。