【4003】编码
Time Limit: 3 second
Memory Limit: 2 MB
【问题描述】
编码工作常被运用于加密文件或压缩传输。这里我们用一种最简单的编码方式进行编码:把一些有规律的单词编成数字。字母表中共有26个字母{a,b,c,…,z},这些特殊的单词长度不超过6且字母按升序排列。把所有这样的单词放在一起,按字典顺序排列,一个单词的编码就对应着它在字典中的位置。
例如:
a→1
b→2
z→26
ab→27
ac→28
abc→352
abd→353
【输入】
仅一行,被编码的单词
【输出】
仅一行,对应的编码。如果单词不在字母表中,输出0。
【输入样例】
ab
【输出样例】
27
【题解】
解释一下样例。
a是1 z 是26,
到了z,没有任何元素可以加了。就让这个字符串变成2位。
我们先变成a,然后要满足从小到大,且字母前一个小于后一个。则变成“ab”
所以ab就是27.
以此规律 我们可以用一个字符串s2,s2一开始=="a",然后我们不断给他最后一位递增.直到为z。
到了z,我们先判断一下是否要增加位数。
这个问题我们用x,y,z来讲。假设我们的3位数变成xyz了,即最后一位是z,且前面的数递减。这个时候我们就会发现没有字母可以递增了。也就是说这个时候要增加string的长度了。则我们随便添加上一个字幕+=“x”;然后从第0到l-1位(string是从0开始的),依次赋值为a,b,c,d。。。。;然后再进行递增。
还有一种情况,就是不用增加位数。
比如tuwxyz;
这里我们先从后往前找到第一个 i 使得a[i] != (a[i+1]-1),即u,然后我们让U递增就好。
每次操作的时候将操作数递增即可。
错误会有出现不是小写字母的情况,还有不是顺序的情况。要注意。
【代码】
#include <cstdio> #include <string> #include <iostream> #include <stdlib.h> using namespace std; string s1; int now = 1; void input_data() { cin >> s1; int ll = s1.size(); ll--; for (int i = 0;i <= ll-1;i++) //这里是判断错误的情况 直接输出0结束程序 { if (s1[i] > s1[i+1]) { printf("0"); exit(0); } if ( s1[i] <'a' || s1[i] > 'z') { printf("0"); exit(0); } } } void get_ans() { string s2 = "a"; //初始化 s2,将s2递增,直到s2 == s1为止 while ( s2 != s1) //每次操作都要递增操作数now { int l = s2.size(); l--; if (s2[l] < 'z') //判断最后一位的情况 如果小于z就可以直接递增 { s2[l]++; now++; } else //如果等于z { bool bo = true; //这里判断是否要增加位数 bo最后如果为true则增加位数 for (int i = l-1;i >= 0;i--) if (s2[i] != (s2[i+1] - 1)) { bo = false; break; } if (bo) //增加位数 { l++; s2+="a";//随便增加 for (int i = 0;i < =l;i++)//最后重新复制成a->a+l-1 s2[i] = 'a' + i; now++; } else //不用增加位数,就从后往前找到一个位置,即可以递增的位置。 { int temp = l-1; while (s2[temp] == s2[temp+1]-1) //这是不能递增的情况,即严格的从z->y->x。。。这样不能递增 temp--; s2[temp]++; for (int i = temp+1;i <= l;i++) s2[i] = s2[i-1] + 1; now++; } } } } void output_ans() { printf("%d",now); //最后输出操作数 } int main() { input_data(); get_ans(); output_ans(); return 0; }