#include #include #include #include #include #include #include #include #include #include using namespace std; #define FI first #define SE second #define X first #define Y second #define ST first #define ND second #define MP make_pair #define PB push_back typedef vector VI; typedef pair PII; typedef long long LL; typedef long double LD; typedef double D; #define REP(i,n) for(int i=0;i<(n);i++) #define FOR(i,a,b) for(int i=(a);i<=(b);i++) #define FORD(i,a,b) for(int i=(a);i>=(b);i--) #define FORE(a,b) for(VAR(a,(b).begin());a!=(b).end();a++) #define VAR(a,b) __typeof(b) a=(b) #define SIZE(a) ((int)(a).size()) #define ALL(x) (x).begin(),(x).end() #define CLR(x,a) memset(x,a,sizeof(x)) int maxKey; const int N = 100025; const LL B = 239; LL h[N]; int t[N]; int nText; LL pB[2 * N]; LL getHash(int l, int r) { if (r < l) { return 0LL; } return (h[r] - (l > 0 ? h[l - 1] : 0)) * pB[nText - r]; } void gen(char* text, char* crib, vector >& res) { int nCrib = strlen(crib); for (int i = 0; i + nCrib <= nText; ++i) { for (int j = 0; j < nCrib; ++j) { int c = text[i + j] - 'A'; c -= int(crib[j] - 'A'); c = (c % 26 + 26) % 26 + 1; t[j] = c; } for (int j = 0; j < nCrib; ++j) { int c = t[j]; if (j > 0) { h[j] = h[j - 1] + c * pB[j]; } else { h[j] = c * pB[j]; } } for (int j = 1; j <= maxKey; ++j) { if (getHash(0, nCrib - j - 1) == getHash(j, nCrib - 1)) { int mv = (j - i % j) % j; res.PB(MP((getHash(mv, j - 1) + pB[mv] * getHash(0, mv - 1)) * pB[nText - mv], MP(i, j))); } } } sort(ALL(res)); int last = 0; for (int i = 0; i < (int) res.size(); ++i) { if (last == 0 || res[i].ST != res[last - 1].ST || i == (int) res.size() - 1 || res[i + 1].ST != res[i].ST) { res[last++] = res[i]; } } res.erase(res.begin() + last, res.end()); } vector > res1, res2; char text[N]; char crib1[105], crib2[105]; vector > ans; int ciph[105]; void alg() { scanf("%s %s %s", crib1, crib2, text); nText = strlen(text); pB[0] = 1; for (int i = 1; i <= 2 * nText + 2; ++i) { pB[i] = pB[i - 1] * B; } res1.clear(); res2.clear(); gen(text, crib1, res1); gen(text, crib2, res2); ans.clear(); int nCrib1 = strlen(crib1); int nCrib2 = strlen(crib2); int jj = 0; for (int i = 0; i < (int) res1.size(); ++i) { while (jj < (int) res2.size() && res2[jj].ST < res1[i].ST) { ++jj; } { if (jj < (int) res2.size() && res2[jj].ST == res1[i].ST && (res1[i].ND.ST + nCrib1 <= res2[jj].ND.ST || res2[jj].ND.ST + nCrib2 <= res1[i].ND.ST)) { ans.PB(res1[i]); } } { ++jj; if (jj < (int) res2.size() && res2[jj].ST == res1[i].ST && (res1[i].ND.ST + nCrib1 <= res2[jj].ND.ST || res2[jj].ND.ST + nCrib2 <= res1[i].ND.ST)) { ans.PB(res1[i]); } --jj; } } if (ans.empty()) { printf("impossible\n"); return; } int mlen = nText +1; LL hmlen; int smlen; FORE (it, ans) { if (it->ND.ND < mlen) { mlen = it->ND.ND; hmlen = it->ST; smlen = it->ND.ST; } } FORE (it, ans) { LL cur = 0; LL hm = hmlen; LL por = it->ST; for (int j = 0; j < it->ND.ND; j += mlen) { cur += hm; hm *= pB[mlen]; if (j > 0) { por *= pB[mlen]; } } if (cur != por) { printf("ambiguous\n"); return; } } int mv = smlen % mlen; for (int j = 0; j < mlen; ++j) { ciph[(mv + j) % mlen] = (int(crib1[j]) - int(text[smlen + j % nCrib1]) + 26) % 26; } for (int i = 0; i < nText; ++i) { int c = text[i] - 'A'; c = (c + ciph[i % mlen]) % 26; putchar(c + 'A'); } putchar('\n'); } int main() { while (scanf("%d", &maxKey) != EOF && maxKey != 0) { alg(); } return 0; }