方法を解決する"Cryptレーニングマッチ対アルゼンチン"行使提案した"プログラミングの課題(プログラミングコンテストトレーニングマニュアル)"?
-
24-09-2019 - |
質問
"プログラミングの課題(プログラミングコンテストトレーニングマニュアル)"が行われたアコースティックライブに行予約アルゴリズム私は決議第11演習が現在と言っても過言ではないと"Cryptレーニングマッチ対アルゼンチン"の問題:
Cryptレーニングマッチ対アルゼンチン
共通の不安定なの暗号化の方法をテキストはpermuteのアルファベットの文字.つまり、アルファベットの各文字は常のテキストによるもの。るための暗号化は可逆、文字を置き換えと同じ。あなたの仕事は復号する複数の符号化されたラインのテキストを想定し、それぞれラインで使用の交換、全ての単語を復号化テキストから辞書れます。
入力
入力にはいくつかのラインを含む整数をn、n小文字の言葉は、インターネットはアルファベット順です。これらのnの言葉を構成する辞書の単語の暗号解読が行われます。
次の辞書が複数行入力します。各線が暗号化された上記のとおりです。が1,000以上の単語を辞書で調べました。ない単語が16を超え します。暗号化されたラインのみを含む大文字小文字および空間 い80文字を超えなさい。
出力
復各線印刷で標準出力に出力します。複数ある場合は、一致します。
がない場合は液を、各文字のアルファベットによるアスタリスク.サンプル入力 6
や
ディック
一般社団法人新経済連盟
シュ
スポット
yertlebjvg xsb hxsn xsb qymm xsb rqat xsb pnetfn
xxxx yyy zzzz www yyyy年次決算bbbb ccc ddddddサンプル出力
ディックは、一般社団法人新経済連盟とパスポットとyertle...
何 戦略 うために、これを解決。と思っていたが、クラシックやbrutish後退、そしていることを避けるまでに発見があります。
PS:この課題に関連して自分の全体ます。
解決
KeyArrayの交換。
スター空KeyArrayこはバージョン0
試合最長の暗号化された単語が最長の辞書に単語を追加KeyArray (これは、私の場合これまでの最長、又はバージョン1.
復文の長cryptedます。
- チェックが暗号解読の文字の文字と同じ 位置に任意の辞書単語の同じ長さです。
- ない場合の試合に戻り、同バージョン0という言葉です。
場合は一部の文字を合、追加の文字をKeyArray、これはバージョン2.
復文の長cryptedます。
- チェックが暗号解読の文字の文字と同じ 位置に任意の辞書。
- ない場合の試合に戻り、同バージョン1という言葉
- 場合は一部の文字を合、追加の文字をKeyArray、これはバージョン3.
まで繰り返しすべての言葉decrypted.
の場合バージョン0の最長の言葉を部分的に復に 短い言葉をもうありません。
他のヒント
マイナーな最適化は、後戻りの実行前に、可能性を列挙することによって行うことができます。 Pythonでます:
dictionary = ['and', 'dick', 'jane', 'puff', 'spot', 'yertle']
line = ['bjvg', 'xsb', 'hxsn', 'xsb', 'qymm', 'xsb', 'rqat', 'xsb', 'pnetfn']
# ------------------------------------
import collections
words_of_length = collections.defaultdict(list)
for word in dictionary:
words_of_length[len(word)].append(word)
possibilities = collections.defaultdict(set)
certainities = {}
for word in line:
length = len(word)
for i, letter in enumerate(word):
if len(words_of_length[length]) == 1:
match = words_of_length[length][0]
certainities[letter] = match[i]
else:
for match in words_of_length[length]:
possibilities[letter].add(match[i])
for letter in certainities.itervalues():
for k in possibilities:
possibilities[k].discard(letter)
for i, j in certainities.iteritems():
possibilities[i] = set([j])
# ------------------------------------
import pprint
pprint.pprint(dict(possibilities))
出力:
{'a': set(['c', 'f', 'o']),
'b': set(['d']),
'e': set(['r']),
'f': set(['l']),
'g': set(['f', 'k']),
'h': set(['j', 'p', 's']),
'j': set(['i', 'p', 'u']),
'm': set(['c', 'f', 'k', 'o']),
'n': set(['e']),
'p': set(['y']),
'q': set(['i', 'j', 'p', 's', 'u']),
'r': set(['j', 'p', 's']),
's': set(['n']),
't': set(['t']),
'v': set(['c', 'f', 'o']),
'x': set(['a']),
'y': set(['i', 'p', 'u'])}
あなたには、いくつかの単一要素の可能性を持っている場合は、入力からそれらを排除し、アルゴリズムを再実行することができます。
編集:の代わりに、リストのセットに交換し、追加印刷コード
私は実際にはかなり異なるアプローチを試してみました。私は、辞書の単語からトライを構築しました。それから私は(DFSでトライをトラバース)再帰的に一緒にトライして文を歩きます。
各スペースで私は私がトライ内の単語の最後にヒットし、ルートへのIループバックがそうであれば確認してください。途中で私は私がこれまでに作った文字の割り当てを追跡します。今までなら、私は私がポイントに再帰を失敗し、UNRAVEL前の割り当てに反する割り当てを持っている私は、次の可能assigmentを作ることができます。
これはトリッキーに聞こえるが、かなりうまく動作するようです。そして、それはコードまで本当に難しいことではありません!
あなたがに対処するための「十分な」テキストを持っていて、テキストの言語を知っていれば別の可能な最適化、あなたは手紙の周波数を使用することができます(参照:http://en.wikipedia.org/wiki/Letter_frequency
を)。これは、6月7日の言葉を扱うときに、もちろん非常に近似的なアプローチですが、あなたは、デコードにいくつかのページを持っている場合は最速の方法となります。
EDIT:Maxのソリューションについて、あなたは、このような手紙を繰り返して、あまりにも、言葉のいくつかの特徴を抽出するために試みることができます。明らかに、暗号化されたテキストで辞書やqymmでパフはダブルレターで終わるだけ4文字の単語であることをリマークは、文字の3のためのまっすぐな答えを与えます。より複雑なシナリオでは、各文字のカップルのための可能性を狭めることができる必要があります。
ここでは、Javaの実施と改善に アルゴリズム 提案@カルロスGutiérrez.
Cryptレーニングマッチ対アルゼンチンのアルゴリズムおよび液に、一体何が悪かったのであろうか。
精密化は、追加の言葉のパターンを減ら検索スペース。例えば、言葉は、"abc"と"女"と同じパターンを"デスクトップ、エンタープライズ"と"女"などの三つの文字の単語が一致しないの牽引文字を別の言葉です。
また、アルゴリズムの実装を再帰的にはより直感的に、良識ある.