题意:

                       已知明文和密文的转换是通过二元对应关系来的...如f(A,Z)代表在明文中的A将在密文中以Z代替...并且也代表了明文中的Z在密文中以A代替...

                       现在给了一些明文的单词(至多20个)...再给了一串密文(总长度至多80)..已知这串密文是由上面某些明文的单词变换而组成的..现在问能否唯一确定密文对应的明文...

              题解:

                       直接DFS就行了....值得注意的是对于密文单词和明文单词..都先确定了长串..再依次往长度小的串确定..效率不是快一点半点..


Program:

#include <iostream>
#include <string.h>
#include <cmath>
#include <algorithm>
#include <stdio.h>
using namespace std;
string s[2000],a[310],out[2000];
char ss[2000];
int turn[360],ans,T[360];
void dfs(int p,int n,int m)
{
int i,x,len=s[p].length(),temp[260];
if (p>m)
{
ans++;
for (x=0;x<26;x++) T[x]=turn[x];
return;
}
for (i=1;i<=n;i++)
{
if (len!=a[i].length()) continue;
for (x=0;x<26;x++) temp[x]=turn[x];
for (x=0;x<len;x++)
{
if (turn[s[p][x]-'A']!=-1 && turn[s[p][x]-'A']!=a[i][x]-'A') break;
if (turn[a[i][x]-'A']!=-1 && turn[a[i][x]-'A']!=s[p][x]-'A') break;
turn[s[p][x]-'A']=a[i][x]-'A',
turn[a[i][x]-'A']=s[p][x]-'A';
}
if (x==len) dfs(p+1,n,m);
if (ans>1) return;
for (x=0;x<26;x++) turn[x]=temp[x];
}
}
bool cmp(string a,string b)
{
if (a.length()!=b.length()) return a.length()>b.length();
return a<b;
}
int main()
{
int n,m,len,x,i;
while (~scanf("%d",&n) && n)
{
for (i=1;i<=n;i++) scanf("%s",ss),a[i]=ss;
sort(a+1,a+1+n,cmp);
m=0;
while (scanf("%s",ss) && ss[strlen(ss)-1]!='.')
s[++m]=ss,out[m]=ss;
ss[strlen(ss)-1]='\0',s[++m]=ss,out[m]=ss;
sort(s+1,s+1+m,cmp);
memset(turn,-1,sizeof(turn));
ans=0;
dfs(1,n,m);
if (ans==1)
{
for (i=1;i<=m;i++)
{
len=out[i].length();
for (x=0;x<len;x++)
printf("%c",T[out[i][x]-'A']+'A');
if (i!=m) printf(" ");
}
puts(".");
}else
puts("-.");
}
return 0;
}