Sicily 4959. Hidden Code

4959. Hidden Code

Constraints

Time Limit: 1 secs, Memory Limit: 256 MB

Description

It’s time to put your hacking skills to the test! You’ve been called upon to help crack enemy codes in the current war on... something or another. Anyway, the point is that you have discovered the encryption technique used by the enemy; it is quite simple, and proceeds as follows. Note that all strings contain only uppercase letters of the alphabet.
1. We are given a key K and a plaintext P which is encrypted character-by-character to produce a ciphertext C of the same length.
2. If |K| is the length of the key K, then the first |K| characters of C are obtained by adding the first |K| characters of P to the characters of K, where adding two letters means interpreting them as numbers (A = 0, B = 1, and so on) and taking the sum modulo 26. That is, Ci = (P+Ki) mod 26 for i = 1, . . . , |K|. If |K| > |P|, then the extra characters in K are ignored.
3. The remaining characters of P, i.e. Pi for i > |K|, are encrypted using the previous ciphertext characters by Ci = (Pi + Ci−|K|) mod 26 for i = |K| + 1, . . . , |P|.
As an example, consider the encryption of the string “STANFORD” using the key “ACM”:
   STA NFORD
+ ACM SVMFA
   -----------------
   SVM FAAWD
Knowing this, you are well on your way to being able to read the enemy’s communications. Luckily, you also have several pairs of plaintexts and ciphertexts which your team recovered, all of which are known to be encrypted with the same key. Help find the key that the enemy is using.

Input

The input consists of multiple test cases. Each test case begins with a line containing a single integer N, 1 <= N <= 100, the number of plaintext and ciphertext pairs you will receive. The next N lines each contain two strings P and C, the plaintext and ciphertext, respectively. P and C will contain only uppercase letters (A-Z) and have the same length (at most 100 characters). The input terminates with a line with N = 0.

Output

For each test case, print a single line that contains the shortest possible key or “Impossible” (quotes added for clarity) if no possible key could have produced all of the encryptions.

Sample Input

1
A B
3
STANFORD SVMFAAWD
AVOWIENR AXAWFEJW
VAMRI VCYMK
3
ABCDEFGHIJKLMNOPQRSTUVWXYZ AAAAAAAAAAAAAAAAAAAAAAAAAA
Y Y
Z Z
2
A B
B A
0
1

Sample Output

B
ACM
AZYXWVUTSRQPONMLKJIHGFEDCB
Impossible

Problem Source

Stanford Programming Contest 2011

// Problem#: 4959
// Submission#: 3372676
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <stdio.h>
#include <iostream>
#include <vector>
#include <string>
#include <stack>
#include <iomanip>
#include <algorithm>
#include <queue>
#include <functional>
#include <map>
#include <string.h>
#include <math.h>
using namespace std;

int N;
vector<pair<string, string> > S;
string K;

void getK(int L) {
    K.push_back('A' + S[0].second[L - 1] - S[0].first[L - 1] + (S[0].second[L - 1] < S[0].first[L - 1] ? 26 : 0));
}

bool test(int n) {
    string P = S[n].first, C = S[n].second, k = K, c;
    c.resize(C.size());
    for (int i = 0, j = 0; i < P.size(); i++) {
        c[i] = (P[i] - 'A' + k[j] - 'A') % 26 + 'A';
        k[j] = c[i];
        if (c[i] != C[i]) return false;
        j = (j + 1) % K.size();
    }
    return true;
}

bool testK() {
    for (int i = 0; i < N; i++) {
        if (!test(i)) return false;
    }
    return true;
}

bool cmp(const pair<string, string> & p1, const pair<string, string> & p2) {
    return p1.first.size() > p2.first.size();
}

int main() {

    std::ios::sync_with_stdio(false);

    while (1) {
        
        K.clear();
        cin >> N;
        if (!N) break;
        S.resize(N);
        for (int i = 0; i < N; i++) cin >> S[i].first >> S[i].second;
        sort(S.begin(), S.end(), cmp);
        int L = 1, maxL = S[0].first.size();
        bool success = false;
        while (L <= maxL) {

            getK(L);
            if (testK()) {
                success = true;
                break;
            } else L++;

        }
        cout << (success ? K : "Impossible") << endl;

    }

    return 0;
}                                 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值