题解 P1079 【Vigenère 密码】
学无止境
2018-02-20 19:43:49
这应该是最短的代码了吧(雾)
**规律:答案是密文的ascll减去密钥的ascll再加上A字母的ascll(还原为大写字母)**
我预处理了一下(还原为大写字母),更方便了。
**Code:**
```
#include<bits/stdc++.h>
using namespace std;
char m[1001],k[101],yclm[1001],yclk[101],ans[1001];//m存的是密文,k是密钥 ,yclm是将m里的密文预处理(全部换为大写),方便解密,yclk一样,ans放答案
int main()
{
scanf("%s%s",k,m);//读入两个字符串
int l_m=strlen(m),l_k=strlen(k);//计算m(密文)的长度,k(密钥)的长度
for(register int i=0;i<l_m;i++)
yclm[i]=toupper(m[i]);//对密文预处理,全部转为大写,存入字符串yclm
for(register int i=0;i<l_k;i++)
yclk[i]=toupper(k[i]);//对密钥预处理,全部转为大写,存入字符串yclk
for(register int i=0;i<l_m;i++)//解密:
ans[i]=yclm[i]-yclk[i%l_k]+'A',ans[i]=ans[i]<'A'?ans[i]+26:ans[i];//观察的规律, yclk[i%l_k]是指密钥重复使用,解密的结果就是——密文的ascll减去密钥的ascll再加上A字母的ascll(还原为大写字母),对于密钥ascll>密文ascll的类型,解密后不在大写字母区间内,再处理,将ascll加上26
for(register int i=0;i<l_m;i++)//还原
cout<<(m[i]>='A'&&m[i]<='Z'?ans[i]:(char)tolower(ans[i]));//如果密文中这个字母是大写, 接输出对应答案;否则是小写,那么将对应答案转为小写再输出
return 0;
}
```
再附无注释代码:
**Code:**
```
#include<bits/stdc++.h>
using namespace std;
char m[1001],k[101],yclm[1001],yclk[101],ans[1001];
int main()
{
scanf("%s%s",k,m);
int l_m=strlen(m),l_k=strlen(k);
for(register int i=0;i<l_m;i++)
yclm[i]=toupper(m[i]);
for(register int i=0;i<l_k;i++)
yclk[i]=toupper(k[i]);
for(register int i=0;i<l_m;i++)
ans[i]=yclm[i]-yclk[i%l_k]+'A',ans[i]=ans[i]<'A'?ans[i]+26:ans[i];
for(register int i=0;i<l_m;i++)
cout<<(m[i]>='A'&&m[i]<='Z'?ans[i]:(char)tolower(ans[i]));
return 0;
}
```