H19:编码(选作)
成绩 | 5 | 开启时间 | 2021年11月1日 星期一 08:00 |
折扣 | 0.8 | 折扣时间 | 2021年11月22日 星期一 23:55 |
允许迟交 | 否 | 关闭时间 | 2021年11月29日 星期一 23:55 |
描述
为了最大程度地节约存储空间,经常需要把信息进行编码。一种很有效的编码方法是用数字来表示一串字符。假设这些字符串都是由不重复的英文小写字母组成的,且每个字符串中的英文字母都是从小到大排列的。
这个编码系统按照如下的方式工作:
- 字符串是按照长度从小到大的顺序排列的
- 长度相同的字符串,是按照字典需排列的
则根据这个编码系统,所有的字符串从 a 开始可以编码如下:
a - 1 b - 2 ... z - 26 ab - 27 ... az - 51 bc - 52 ... vwxyz - 83681 ...
那么,请编程计算出一个字符串在这个编码系统下编码后的值是多少。
输入
输入的第一行为 N,表示有 N 组数据。后面的 N 行每行包含一个不超过 10 个字母的字符串。
输出
输出字符串所对应的编码,如果该字符串不能被编码,则输出 0。
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
| 以文本方式显示
| 1秒 | 30720KB | 0 |
测试用例 3 | 以文本方式显示
| 以文本方式显示
| 1秒 | 30720KB | 0 |
测试用例 4 | 以文本方式显示
| 以文本方式显示
| 1秒 | 30720KB | 0 |
题目分析:模拟进位,核心在于必须按照字典序排列 例如bz完后是cd。
为了简便,易操作,先用gets获得字符串后转化为整形数组便于操作(感觉不转化也可以)
例如 cfg转化为3,6,7 转化完后的整形数组就是我们的目标数组
目标数组是什么意思呢? 我们还需要新建一个数组,让这个数组像一个26进制的数字(但考虑到字典序,其实并不是26进制) 让这个“数字”不断+1,同时让value(答案)+1,当这个“数字”和目标数组(其实也是个数字)相等时,输出value 。至于一共输入N组数据以及判断是否编码,只能说它烦人,但是还是比较容易实现的。
代码如下
#include <stdio.h>
#include <string.h>
int main() {
int N;
scanf("%d", &N);
char useless = getchar();
int i = 1;
loop:
while (i <= N) {
i++;
char s[11];
gets(s);
for (int i = 0; i < strlen(s) - 1; i++) {
if (s[i] >= s[i + 1]) {
printf("0\n");
goto loop;
}
}
int a[11];
int equal(int *, int *, int);
for (int i = 0; i < strlen(s); i++) { //累加的目标是数组a
a[i] = s[i] - 'a' + 1; //a数组中1~26对应a ~ z
}
int len = strlen(s) - 1;
int b[11] = {0};
int value = 0;
int count = 0;
while (!equal(a, b, len)) { //一直加直到ab数组相同
b[len]++;
value++;
if (b[len] == 27) {
count = 0; //记录位数
b[len] -= 1;
while (b[len - count] == 26 - count) {//b[len-count]是第几位
count++;
} //while用来找进位几次
b[len - count] += 1;
for (int i = 1; i <= len; i++)
b[len - count + i] = b[len - count] + i; //按字典序排列
}
}
printf("%d\n", value);
}
return 0;
}
int equal(int *x, int *y, int size) {
for (int i = 0; i <= size; i++) {
if (x[i] != y[i])
return 0;
}
return 1;
}
1、因为我们抛弃了字符数组,使用整形数组,自然不能使用strcmp函数,于是新写一个类似的整型数组的strcmp函数判断是否达到目标数组。
2、核心代码 while(!equal(a,b,len))中的if : if判断是否到了进位的时候,如果是,判断进几次位
判断方法: 例如b数组是16,24,25,26 就从26这个位置数,知道前n位不满足26-n,让第前n+1位进位,16+1=17,然后将24,25,26位置变成 18,19,20。
3、预处理比较多,但都比较自然。例如 scanf后要加getchar吸收空格让gets符合期望 用goto是当不能编码的时候 跳过下面的核心代码