p1449 字符串还原
描述
一个长度为n的由小写字母组成的字符串s_1~s_2~\cdots~s_n~s
1、将字符串翻转,即对于每一个1 ≤ i ≤ n来说,si与s(n-i+1)对换。
2、将字符串中每个字母变为其之后第k个字母,定义z之后的字母为a,其中0 ≤ k ≤ 6且为未知数
3、将字符串中每个字母变为其之前第k个字母,定义a之前的字母为z,k同2所述。
例如字符串abcd按上面3种方式加密后,在k=1的情况下会依次变为:
1、dcba;
2、bcde;
3、zabc。
现给出信中按以上3种形式分别加密后的3个字符串(不一定按上述例子的顺序),要求还原原来的字符串,并输出告诉小K。
格式
输入格式
输入的第1行为一个整数n,表示这个字符串的长度。
下面3行每行1个长度为n的字符串,且保证符合题目要求。
输出格式
输出仅包括1行,为还原后的字符串。
样例1
样例输入1
4
zabc
dcba
bcde
样例输出1
abcd
思路
题干中指出只有三种变换方式,不管怎么变换,三种密文的头字母或者尾字母是相互之间存在联系的。我们以头字母为例,假设明文的头字母为a,移动数k为1,则以3)为条件变换的密文的头字母则为'a+26-1',以2)为条件变换的密文的头字母则为'a+1',以1)为条件变换的密文的尾字母即为头字母,故将3)与2)的头字母相加减去1)的尾字母得到的数为26。当头字母处于字母表末位的时候数字会超出26,此时我们使用模运算为0即可,类似循环队列的做法。
代码
#include <stdio.h> #include <stdlib.h> #define MAX 10000+10 void reverse(char str[],int n); int main(){ char a[MAX], b[MAX], c[MAX]; int n; scanf("%d",&n); scanf("%s %s %s",a,b,c); if((a[0]+b[0]-c[n-1]-c[n-1])==26){ reverse(c,n); } else if((a[0]+c[0]-b[n-1]-b[n-1])==26){ reverse(b,n); } else{ reverse(a,n); } return 0; } void reverse(char str[],int n){ char res[MAX]; int i; for(i=n-1;i>=0;i--){ res[n-1-i]=str[i]; } res[n]='\0'; printf("%s",res); }
troubleshooting
由于没有反序转换字符串的函数,所以这里我们要自己动手,特别注意的是字符串结尾存储的是'\0',这里需要手动加上(来自yachen大神的提醒)。