UVALive - 4380 Javanese Cryptoanalysis

Uvalive 4380

题意是给出一段密文,要求找出找一种解密方式,使得解密后的文本,任意一个单词都是元辅音间隔形成的。
数据输入比较恶心,单词之间可以是空格间隔,也可以是换行符间隔,因此必须读到一个空的行才表示一个TestCase结束。
输入的文本,处理出所有单词相邻字母的情况,存储在一个26*26的二维数组中,G[u][v]表示’A’+u与’A’+v在密文中相邻。
五重循环,枚举原文中的五种元音:AEIOU,分别对应密文中的哪几个字母,那么剩下的辅音字母就对应密文中未被映射的字母。
根据枚举出来的映射判断原文中是否存在元音相邻,或者辅音相邻的情况,存在则继续枚举,不存在则有解,根据映射输出原文即可。
TestCase之间要输出一个空行。

#include<map>
#include<queue>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#define LL long long
#define LLU long long usigned
#define ls (root<<1)
#define rs (root<<1|1)
#define LSON  ls,l,mid
#define RSON rs,mid+1,r
#define mm(a,b) memset(a,b,sizeof(a))
#define cl(a) memset(a,0,sizeof(a))
#define mm0x3f(a) memset(a,0x3f,sizeof(a))
#define mm_1(a) memset(a,-1,sizeof(a))
#define debug puts("It's o k here")
#define mp make_pair
#define rep(a,b,c) for(int a=(b);a<(c);a++)
using namespace std;
const int Inf=0x3f3f3f3f;
const int maxn=1e6+5;
const int maxnode=1e5+5;
const int sigma_size=26;
const int maxs=105;//pattern string numbers
const int maxt=1e3+5;

int n, m;
char s[maxn];
int G[sigma_size][sigma_size];
int vow[sigma_size], oth[sigma_size];
int vow_cnt, oth_cnt;
int is_vowel[26];
int v[5], v2[26];
vector<string> sset;
void output(){
//    for(int i=0;i<5;i++)
//        printf("%c ",v[i]+'A');
//    for(int i=0;i<26;i++)
//    if(!is_vowel[i]) printf("%c->%c\n", 'A'+i, v2[i]+'A');
//    puts("");

    for(int si=0;si<sset.size();si++){
        n=sset[si].length();
        for(int i=0;i<n;i++)
        if(sset[si][i]!=' '){
            int j=sset[si][i]-'A';
            if(j==v[0]) printf("A");
            else if(j==v[1]) printf("E");
            else if(j==v[2]) printf("I");
            else if(j==v[3]) printf("O");
            else if(j==v[4]) printf("U");
            else printf("%c",v2[j]+'A');
        }
        else printf(" ");
        puts("");
    }
}
void solve(){
    int no_ans=0;
    for(v[0]=0;v[0]<26;v[0]++)
    for(v[1]=v[0]+1;v[1]<26;v[1]++)
    for(v[2]=v[1]+1;v[2]<26;v[2]++)
    for(v[3]=v[2]+1;v[3]<26;v[3]++)
    for(v[4]=v[3]+1;v[4]<26;v[4]++){//map vowels in source text to character in encoded text
        no_ans=0; cl(is_vowel);
        for(int i=0;i<5;i++) is_vowel[v[i]]=1;
        for(int i=0;i<5&&!no_ans;i++)
        for(int j=0;j<5&&!no_ans;j++)
        if(G[v[i]][v[j]])  no_ans=1;
        if(no_ans){
            continue;
        }

        for(int i=0;i<26&&!no_ans;i++)
        for(int j=0;j<26&&!no_ans;j++)
        if(!is_vowel[i]&&!is_vowel[j]&&G[i][j]) no_ans=1;
        if(no_ans){
            continue;
        }

        for(int i=0, j=0;i<26;i++)
        if(!is_vowel[i]){
            v2[i]=oth[j++];
        }
        output();
        return;
    }
    puts("impossible");
}
int main(){
    int T, cas=0;
    bool flag;

    for(int i=0;i<26;i++)
    if('A'+i!='A'&&'A'+i!='E'&&'A'+i!='I'&&'A'+i!='O'&&'A'+i!='U'){
        oth[oth_cnt++]=i;
    }

    while(gets(s)){
        sset.clear();
        if(cas++!=0) printf("\n");
        cl(G); cl(is_vowel);
        do{
            n=strlen(s);
            for(int i=1;i<n;i++)
            if(s[i-1]!=' '&&s[i]!=' '){
                int u=s[i-1]-'A';
                int v=s[i]-'A';
                G[u][v]=1; G[v][u]=1;
            }
            sset.push_back(string(s));
        }while((flag=gets(s))&&s[0]);
        solve();
        if(!flag) break;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值