[BZOJ2145]悄悄话

来源:互联网 发布:sem老虎优化方案 编辑:程序博客网 时间:2024/04/29 09:46

题意:给出用凯撒加密法加密后的密文,求原文。

这道题让我想起了三年前做的唐教出那个提交答案题,那道题的加密是一个全排列,破解起来非常困难,当时和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;}


0 0
原创粉丝点击