OpenJudge 1.13-51:古代密碼 題解
51:古代密碼
描述(此描述太繁瑣,你可以忽略,下文有註解)
古羅馬帝國有一個擁有各種部門的強大政府組織。其中一個部門就是保密服務部門。為了保險起見,在省與省之間傳遞的重要檔案中的大寫字母是加密的。當時最流行的加密方法是替換和重新排列。
替換方法是將所有出現的字元替換成其它的字元。有些字元會替換成它自己。例如:替換規則可以是將'A' 到 'Y'替換成它的下一個字元,將'Z'替換成 'A',如果原詞是 "VICTORIOUS" 則它變成 "WJDUPSJPVT"。(下文有註解)
排列方法改變原來單詞中字母的順序。例如:將順序<2, 1, 5, 4, 3, 7, 6, 10, 9, 8>(原題在此處有誤,此資料來自
人們很快意識到單獨應用替換方法或排列方法加密,都是很不保險的。但是如果結合這兩種方法,在當時就可以得到非常可靠的加密方法。所以,很多重要資訊先使用替換方法加密,再將加密的結果用排列的方法加密。用兩種方法結合就可以將"VICTORIOUS" 加密成"JWPUDJSTVP"。
考古學家最近在一個石臺上發現了一些資訊。初看起來它們毫無意義,所以有人設想它們可能是用替換和排列的方法被加密了。人們試著解讀了石臺上的密碼,現在他們想檢查解讀的是否正確。他們需要一個計算機程式來驗證,你的任務就是寫這個驗證程式。
輸入輸入有兩行。第一行是石臺上的文字。文字中沒有空格,並且只有大寫英文字母。第二行是被解讀出來的加密前的文字。第二行也是由大寫英文字母構成的。
兩行字元數目的長度都不超過100。輸出如果第二行經過某種加密方法後可以產生第一行的資訊,輸出 "YES",否則輸出"NO"。
樣例輸入
JWPUDJSTVP
VICTORIOUS
樣例輸入
YES
題解
好吧,其實這道題最難的就是描述,這道語文題 其實是這樣的:
給你兩個字串,例如:
JWPUDJSTVP
VICTORIOUS(長度相等,無空格)(測試資料也沒有坑人)
你只能進行兩個操作,替換字母,重新排列
能否將第一行字串 改為 第二行字串
替換字母:
題目只是舉了一個替換的例子,同一個資料沒有唯一的替換規律
只要滿足一 一對應就可以
如
ABC
ADF
是合法的(自己可以翻譯成自己)
但
ABC
ABA
不合法("A"and"C"都翻譯成了"A")
或
AAA
ABC
不合法("A"翻譯成了三個不同答案)
重新排列:
排列方法也是隨便的
沒有一定規律
(說白了就是你可以隨便換字母的"位置")
既然位置不做要求,你應該馬上想到一個東西 桶
大致思路如下:
用p1,p2兩個桶分別統計兩個字串中出現i(1,2,3,4......)次的字母種類的個數("桶中桶",此處需細細咀嚼,可結合程式碼)
只要桶(大桶)中內容相等就cout<<"YES"; else就NO啦
那麼就上程式碼吧!
#include<bits/stdc++.h> using namespace std; string a,b; int i,t1[150],t2[150],p1[150],p2[150],len; //t1,t2下標為"A"~"Z" //統計該字母出現次數 //p1,p2下標一定小於總長度(0次也統計了,但無需比較) //統計t1及t2內容相等的桶的個數 bool f(string a,string b)//寫在函式裡,(強迫症)倒沒有什麼特殊意義 { for(i=0;i<len;i++) { t1[a[i]]++; t2[b[i]]++; } for(i='A';i<='Z';i++) { p1[t1[i]]++; p2[t2[i]]++; } for(i=1;i<=len;i++)//這裡的迴圈條件需注意一下 if(p1[i]!=p2[i]) return false; return true; } int main() { cin>>a>>b; len=a.size(); if(f(a,b)) cout<<"YES"; else cout<<"NO"; return 0; }
當然,這道題還有一種優化方案
可以把大桶省去(此方案也可能更好理解)
"這樣不便於理解,運用桶是為了解決無序序列的比對,那麼把無序變為有序,不就好了嗎"
——引用自某教師
那sort一下就OK了
#include<bits/stdc++.h> using namespace std; string s1,s2; int t1[150],t2[150]; int len,i; int main() { cin>>s1>>s2; len=s1.size(); for(i=0;i<len;i++) { t1[s1[i]]++; t2[s2[i]]++; } sort(t1+'A',t1+'Z'+1);//這裡的引數注意一下 sort(t2+'A',t2+'Z'+1);//不理解問度娘sort的工作原理 for(i='A';i<='Z';i++) { if(t1[i]!=t2[i]) { cout<<"NO"; return 0; } } cout<<"YES"; return 0; }
結尾百科鎮貼