题意:给出用凯撒加密法加密后的密文,求原文。
这道题让我想起了三年前做的唐教出那个提交答案题,那道题的加密是一个全排列,破解起来非常困难,当时和lzm他们一群人在机房开黑搞这题搞了一整场考试的时间,得了60分23333
这个题凯撒加密的方法只有26种,可以枚举判断。
其实APIO上讲课时提到过这个题的。但是我看了题目后发现他保证句子长度大于等于3,又没有保证是从哪里截取的自然英文还是出题人刻意造的刁钻句子,所以显然不能直接统计字母频率。。
最好的方法是从单词下手。我差不多用了一个小时想了一些常见单词还有词缀,然后乱搞了些参数。后来搞到数据测了一下,发现只有10分。。本来设置了一个子串识别功能,就是一个单词的子串出现在单词表中时也要加分,并且长度越大加的分越大,后来发现一个被错误解密的单词中竟然完整地包含了一个"there"我了个大擦!于是我(面向数据)加了个限制就是子串重合的话必须要超过5个字母23333
后来调了很久发现始终只能得60分左右,就又去查看了一波数据,发现有一个句子其中一大半的单词都在我的单词表中但是没翻译对,然后我发现我提取出来单词后没封斜杠0,相当于我之前写的单词识别部分只有第一个单词识别对了!汗这也能过60。。。加上个memset之后终于A了。。。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<map>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define erp(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
typedef unsigned long long u64;
char buf[10000], s[10000], word[10000], d[10000], ss[10000];
bool yuan[26];
map<u64, int> ha;
char dict[1000][30] = {
"am","is","are","was","were","been",
"a","an","the","this","that","these","those","there","even",
"i","me","my","you","your","he","his","him","she","her","hers","we","our","ours","it","its",
"up","to","for","in","out","of","on","above","below","over","under","into","after","before",
"what","where","when","how","why","if","then","else","begin","end","while","break","continue",
"yes","no","never","ever","sure","thank","thanks","welcome","sorry","and","or","but","though","although",
"morning","afternoon","evening","nignt","please","file"
};
char noun[1000][30] = {
"tom","bob","alice","david","james","peter","tony","friend","wife","husband","aunt","uncle",
"book","desk","table","computer","bed","pen","man","woman","women","men","boy","girl","people","time","kid","child",
"cat","dog","cow","pig","mouse","mice","rice","one","two","three","four","five","six","seven","eight","nine","ten",
"son","daughter","shower","rain","weather","sun","sunny","wind","snow","fire","water","river","sea",
"window","floor","house","room","door","way","road","street","light","word",
"car","bike","bus","truck","plane","air","king","queen","sodier",
"dollars","money","cake","bread","math","chinese","english","hand","eye","head","body","mouth",
"apple","banana","orange","pear","tree","grass","melon","bush",
"city","country","nation","flag","breakfast","lunch","dinner"
};
char ad[1000][30] = {
"good","well","bad","nice","beautiful","better","worse","happy","glad","sad","other","recent"
"green","white","yellow","blue","red","purple","big","large","small","again","just",
"lot","lots","some","many","so","first","second","last","early","late","sweet","new","old","young"
};
char verb[1000][30] = {
"must","might","should","can","could","may",
"do","did","play","like","want","love","go","went","gone","say","said","sais","test","make","get","getting","got",
"have","has","had","will","shall","use","try","read","write","see","saw","seen","look","smell","smelt","hear","heard",
"exciting","intersting","came","find","found","wash","clean","sleep","eat","drink","take","took","taken","fly","cook"
"give","gave","given","hide","hid","hidden","swim","swam","run","walk","walked","pay","paid"
};
char suffix[1000][30] = {
"s","es","ing","ed","ies","ly","ty","teen","er","ers","tant","tent","ists","ve",
"ever","room","ious","ish","tion","age","ache","ster","ant","nal","tal","cal","sal","ple"
};
char prefix[1000][30] = {
"dis","des","pre","in","im","un","anti","sub","con","com","under","over","ex",
"re","ist","ists","en","trans","bi","mono","tri","octo","inter","ele","tele"
};
bool rec_upper[10000];
int val[30];
int trans(char c, int v)
{
if (!isalpha(c)) return c;
int a = c;
if (islower(c)) { a += v; if (a>'z') a-=26; }
else { a += v; if (a>'Z') a-=26; }
return a;
}
int sum[26], bd[26];
void deal_word(int len, int totwd)
{
memset(d,0,sizeof d);
for (int x = 0; x<26; ++x)
{
int xflag = 0;
for (int i = 0; i<len; ++i) d[i] = trans(word[i], x);
if (rec_upper[0] && len==1 && d[0]!='i') { val[x]-=99999; continue; }
for (int i = 0; dict[i][0]; ++i)
if (strcmp(dict[i], d)==0)
{
if (len==1) val[x] += 5;
else if (len>5) val[x] += 99999;
else if (len>=5) val[x] += len*len*len*15;
else val[x] += len*20;
sum[x]++;
}
for (int i = 0; ad[i][0]; ++i)
if (strcmp(ad[i], d)==0)
{
if (len==1) val[x] += 5;
else if (len>5) val[x] += 99999;
else if (len>=5) val[x] += len*len*len*15;
else val[x] += len*20;
sum[x]++;
}
for (int i = 0; noun[i][0]; ++i)
if (strcmp(noun[i], d)==0)
{
if (len==1) val[x] += 5;
else if (len>5) val[x] += 99999;
else if (len>=5) val[x] += len*len*len*15;
else val[x] += len*20;
sum[x]++;
}
for (int i = 0; verb[i][0]; ++i)
if (strcmp(verb[i], d)==0)
{
if (len==1) val[x] += 5;
else if (len>5) val[x] += 99999;
else if (len>=5) val[x] += len*len*len*15;
else val[x] += len*20;
sum[x]++;
}
for (int i = 0; prefix[i][0]; ++i)
{
bool flag = 1;
for (int j = 0; prefix[i][j]; ++j) if (d[j]!=prefix[i][j]){flag=0;break;}
if (flag) val[x] += strlen(prefix[i])*strlen(prefix[i])*strlen(prefix[i])*6;
}
for (int i = 1, t; suffix[i][0]; --i)
{
bool flag = 1; t=strlen(suffix[i]);
for (int j = 0; j<len&&j<t&&t<=len; ++j) if (d[len-i-1]!=suffix[i][t-j-1]) {flag=0;break;}
if (flag) val[x] += t*t*t*6;
}
for (int i = 0; d[i]; ++i)
{
u64 h = 0;
for (int j = i, k; d[j]; ++j)
{
h = h*31+d[j]-'a'+1;
if ((k=ha[h])>4) val[x] += k*k*k*8;
}
}
for (int i = 0; d[i]&&d[i+1]; ++i)
{
if (rec_upper[i]) continue;
if (yuan[d[i]-'a']^yuan[d[i+1]-'a'])
val[x] ++;
if (d[i+2] && yuan[d[i]-'a']==yuan[d[i+1]-'a']&&yuan[d[i]-'a']==yuan[d[i+2]-'a'])
{
if(d[i]=='g'&&d[i+1]=='h'&&d[i+2]=='t')continue;
if (yuan[d[i]-'a']) bd[x]+=2;
else bd[x]++;
if (bd[x]>=5) val[x] -= 99999;
}
}
}
}
void deal_string(int len, int xn)
{
bool flag = 0;
for (int i = 0; i<len; ++i)
if (isalpha(s[i])) flag = 1;
if (!flag) return;
int t = 0;
for (int i = 0; i<=len; ++i)
{
if (!isalpha(s[i])) word[t]='\0', deal_word(t, xn), t = 0, memset(word,0,sizeof word);
else {
if (isupper(s[i])) word[t] = tolower(s[i]), rec_upper[t] = 1, t++;
else word[t] = s[i], rec_upper[t] = 0, t++;
}
}
}
void solve()
{
memset(buf, 0, sizeof buf);
memset(s, 0, sizeof s);
memset(sum,0,sizeof sum);
memset(bd, 0, sizeof bd);
gets(buf);
memset(val, 0, sizeof val);
int i = 0, j = 0, len = strlen(buf), xn = 1;
for (i = 0; i<len; ++i) if(buf[i]==' ') xn++;
for (i = j = 0; i<len; i+=j)
{
while ((buf[i]==' '||buf[i]=='\n'||buf[i]=='\t'||buf[i]=='\r')&&i<len) ++i;
for (j = 0; buf[i+j]!=' '&&buf[i+j]!='\n'&&buf[i+j]!='\r'&&buf[i+j]!='\t'&&buf[i+j]; j++) s[j] = buf[i+j];
deal_string(j, xn); memset(s, 0, sizeof s);
}
for (int i = 0; i<26; ++i) if (xn>=10?(sum[i]>=xn/3):(sum[i]>=xn/2)) val[i]+=1234;
int opt = 0;
for (int i = 1; i<26; ++i) if(val[i]>val[opt]) opt = i;
for (i = 0; i<len; ++i) if (isalpha(buf[i])) putchar(trans(buf[i], opt)); else putchar(buf[i]);
puts("");
}
void GlobalHash()
{
for (int i = 0; dict[i][0]; ++i)
{
u64 h = 0;
if (strlen(dict[i])<3) continue;
for (int j = 0; dict[i][j]; ++j) h = h*31+dict[i][j]-'a'+1;
ha[h] = strlen(dict[i]);
}
for (int i = 0; noun[i][0]; ++i)
{
u64 h = 0;
if (strlen(noun[i])<3) continue;
for (int j = 0; noun[i][j]; ++j) h = h*31+noun[i][j]-'a'+1;
ha[h] = strlen(noun[i]);
}
for (int i = 0; verb[i][0]; ++i)
{
u64 h = 0;
if (strlen(verb[i])<3) continue;
for (int j = 0; verb[i][j]; ++j) h = h*31+verb[i][j]-'a'+1;
ha[h] = strlen(verb[i]);
}
for (int i = 0; ad[i][0]; ++i)
{
u64 h = 0;
if (strlen(ad[i])<3) continue;
for (int j = 0; ad[i][j]; ++j) h = h*31+ad[i][j]-'a'+1;
ha[h] = strlen(ad[i]);
}
}
int main()
{
freopen("msg.in", "r", stdin);
freopen("msg.out", "w", stdout);
yuan[0]=yuan['e'-'a']=yuan['i'-'a']=yuan['o'-'a']=yuan['u'-'a']=1;
GlobalHash();
rep(i, 1, 10)
solve();
return 0;
}