UVa 468
題目
http://domen111.github.io/UVa-Easy-Viewer/?468
我們今天設計了一個新的加密方式,首先是先寫下明文 $P$
接下來我們會分析 $P$ 當中每個字母出現的頻率
接下來建立一個對照的字串 $S$ , $S$ 當中每個字都會對應到 $P$ 的某個相同出現頻率的字
我們保證題目當中只會出現字母,並且每個字母的出現頻率都不相同
如果給你 $S$ 以及加密後的密文 $C$,你可以找到 $P$ 嗎?
想法
因為每個字母出現的頻率都是獨特的,所以我們可以先分別統計 $P$ 和 $S$ 的每個字母出現次數
經過排序過後就可以很快對應出每個字母應該要對應到誰
最後建立一個對照表,輸出對著這張表就可以了
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| #include<iostream> #include<algorithm> using namespace std;
const int Max = 1e9+10; int n; char tbl[128]; bool out=false; string s;
struct statistics{ char alpha; int cnt=Max; };
bool cmp(statistics p, statistics q){ if(p.cnt != q.cnt) return p.cnt < q.cnt; return false; }
int main(){ cin>>n; while(n--){ if(out) cout<<"\n"; else out=true; statistics text[128], cipher[128]; for(int i=65 ; i<123 ; i++){ text[i].alpha = cipher[i].alpha = char(i); text[i].cnt = cipher[i].cnt = 0; } cin>>s; for(int i=0 ; i<s.size() ; i++){ text[s[i]].cnt++; } cin>>s; for(int i=0 ; i<s.size() ; i++){ cipher[s[i]].cnt++; } sort(text, text+128, cmp); sort(cipher, cipher+128, cmp); for(int i=0 ; cipher[i].cnt!=Max ; i++){ tbl[cipher[i].alpha] = text[i].alpha; } for(int i=0 ; i<s.size() ; i++){ cout<<tbl[s[i]]; } cout<<"\n"; } return 0; }
|
時間複雜度分析
每筆測資輸入時間複雜度為 $O(len(P) + len(C))$
每筆測資統計時間複雜度為 $O(len(P) + len(C))$
每筆測資排序時間複雜度為 $O(2mlogm)$ ,其中 $m = 128$
每筆測資輸出時間複雜度為 $O(len(C))$
總時間複雜度約為 $n(2(len(P) + len(C)) + 2mlogm + len(C))$