1. 程式人生 > >OpenJudge 1.13-51:古代密碼 題解

OpenJudge 1.13-51:古代密碼 題解

原題連結

51:古代密碼

 描述(此描述太繁瑣,你可以忽略,下文有註解)

古羅馬帝國有一個擁有各種部門的強大政府組織。其中一個部門就是保密服務部門。為了保險起見,在省與省之間傳遞的重要檔案中的大寫字母是加密的。當時最流行的加密方法是替換重新排列

替換方法是將所有出現的字元替換成其它的字元。有些字元會替換成它自己。例如:替換規則可以是將'A' 到 'Y'替換成它的下一個字元,將'Z'替換成 'A',如果原詞是 "VICTORIOUS" 則它變成 "WJDUPSJPVT"。(下文有註解)

排列方法改變原來單詞中字母的順序。例如:將順序<2, 1, 5, 4, 3, 7, 6, 10, 9, 8>(原題在此處有誤,此資料來自

英文版)應用到 "VICTORIOUS" 上,則得到"IVOTCIRSUO"。

人們很快意識到單獨應用替換方法或排列方法加密,都是很不保險的。但是如果結合這兩種方法,在當時就可以得到非常可靠的加密方法。所以,很多重要資訊先使用替換方法加密,再將加密的結果用排列的方法加密。用兩種方法結合就可以將"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;    
} 

 

 結尾百科鎮貼