[Atelier Blue アトリエブルー]Homeコンテストパソコン甲子園2003年本選>20問目

20問目(シーザー暗号、解読、文字列マッチ)

問題

文字をずらすことによって作られる暗号をシーザー暗号といいます。今回はアルファベット小文字a...zをずらすことによって出来た暗号を復号化します(右に1文字ずらすとzはぐるっと回ってaになります)。

入力されるのは暗号化された文字列です。ヒントは復号化した文字列にthe,this,thatのいずれかの単語が含まれていることです。今回は、この単語のいずれかが含まれていれば復号化した文字列を出力し終了してください。

暗号化されたデータに含まれる文字はアルファベットの小文字、ピリオド、空白、改行のみです。このうち暗号化を行っているのはアルファベット小文字のみです。また、文字数は80文字以下です。

詳しくは原文参照。

入力

暗号化された文字列

出力

複合化した文字列

入力例

xlmw mw xli tmgxyvi xlex m xsso mr xli xvmt.

出力例

this is the picture that i took in the trip.

解き方例

文字列マッチします。その際、ちゃんと単語になっているように注意します。他の単語の一部分にマッチしないようにしましょう。

ソースコード

お持ち帰り

C/C++

#include <stdio.h>
#include <string.h>

int scan(char *str,int max)
{
    int i;
    for(i=0;i<max;i++){
        if(!strncmp(&(str[i]),"this ",5))return 1;
        if(!strncmp(&(str[i]),"that ",5))return 1;
        if(!strncmp(&(str[i]),"the ",4))return 1;
        if(!strncmp(&(str[i]),"this.",5))return 1;
        if(!strncmp(&(str[i]),"that.",5))return 1;
        if(!strncmp(&(str[i]),"the.",4))return 1;

        //次の単語の始まりをさがす
        for(i++;;i++){
            if(str[i] == ' ' || str[i] == '.'){
                break;
            }
        }
    }
    return 0;
}

int main(){
    char in[82];
    int n,i;
    gets(in);

    n = strlen(in);

    while(1){
        for(i=0;i<n;i++){
            if(in[i] !=' ' && in[i] != '.'){
                in[i] = in[i] + 1;
                if(in[i] == 'z'+1)in[i] ='a';

            }
        }
        if(scan(in,n))break;
    }
    printf("%s\n",in);
    return 0;
}



その他

今回のマッチ作業は非常に効率が悪いです。ですが、まあ、こんなモンでしょう。最初は単純に1文字ずつずらしながらマッチしていましたが、それだと他の単語の途中にマッチする可能性があったので改良しました。実際にはもう3通り最後が改行になっている文字列ともマッチした方が良かったのですが、それは省略です。きっとピリオドで終わってくれるでしょう。


ページの一番上へ
前のページへ 一覧に戻る 次のページへ
初版2006--
[Atelier Blue アトリエブルー]Homeコンテストパソコン甲子園2003年本選>20問目