Sicily 1213. 打开遗迹之门

1213. 打开遗迹之门

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

NightElf是一个古老的种族,在他们的遗迹上到处都有古NightElf的奇妙文字,这些文字都是一些十分美妙而复杂的符号。然而,现在的NightElf人早已不认识古文字了,因为古文字过于复杂,早在几十个世纪之前,他们就改用简单的英文字母来代替古代的文字符号,每个古文字符号对应一个英文字母。当然,正是因为对应关系渐渐的被人遗忘了,所以古代文字已经无法卒读了。除了这一点之外,古语同现代语没有任何区别。

有一天,探险家Arthas在一个古老的NightElf遗迹前面被一扇大门给拦住了。大门上用古NightElf文字刻着一句话。当地人告诉他,只有知道这句话的意思,解出一个谜题,才能进入这个遗迹。
于是,Arthas下决心要找出古文字和现代的英文字母之间的联系,理解出这句话的含义。然而这并不是一件轻松的工作。所幸,他的一个朋友是语言学家,告诉了他一些很重要的事实:
NightElf文字共有n(1<=n<=27)个字母。其中n-1个文字是有意义的,这n-1个文字在现代语中用小写英文字母a,b,c.....中的前n-1个表示。还有一个文字是分隔符。在句子中每两个单词之间有且只有一个分隔符,将单词隔开。另外,NightElf语言中每个单词有着非常丰富的意思,因此只有很少的单词。

当然,遗迹大门上的那一句话中的每个单词都应该是NightElf语言中的合法单词。于是Arthas便想通过了解NightElf语言中的所有单词,来试着找出句子的含义。

Input

第一行一个整数t,表示有t组数据。
每组数据第一行是两个整数n(1=<n<=27)和m(1=<m<=200),分别表示NightElf语言的字符数和句子的字符数。
接着一行有m个整数,每个整数都在1到n之间,且1到n中的每一个数都会出现。每个数代表一个古NightElf语言的文字符号,相同的数字表示相同的文字符号。
再来是一个整数q(1=<q<=200),表示NightElf语言的单词数。
接下来有q行,每行一个由现代语写出的(即用小写英文字母表示)单词。每个单词的长度不超过10。

Output

输出只有一行,是Arthas该句子分析的结果:
  如果句子只有唯一的可能,将它翻译成现代语输出
  如果没有任何可能的单词组合组成句子,输出No solution
  如果句子有多种可能的组合,输出Cannot determine

Sample Input

1
5 18
3 2 1 3 5 4 2 1 1 5 2 4 3 4 5 3 4 1
14
adca
bacb
cacc
adba
cabb
bdcc
dacc
baaa
dbab
acbc
daba
cba
abc
dcb

Sample Output

adca bdcc dbab abc

Problem Source

ZSUACM Team Member

// Problem#: 1213
// Submission#: 3586094
// 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 <string.h>

int n, m, q;
char num2str[30];
char words[205][11];
int wl[205];
char senChar[205];
int senNum[205];
int deli;
bool wordLength[11];
int answerNum;
bool anAns;
char ansNum2str[30];

int w[205][2];
int wn;

bool check() {
    int sp = 0;
    wn = 0;
    if (senNum[0] == deli || senNum[m - 1] == deli) return false;
    for (int i = 0; i < m; i++) {
        if (senNum[i] == deli) {
            if (!wordLength[i - sp]) return false;
            w[wn][0] = sp;
            w[wn][1] = i - 1;
            wn++;
            sp = i + 1;
        }
    }
    if (!wordLength[m - sp]) return false;
    w[wn][0] = sp;
    w[wn][1] = m - 1;
    wn++;
    return true;
}

bool isOK(int numNow, int charNow) {
    
    bool existChar[30];
    memset(existChar, false, sizeof(existChar));
    for (int i = 1; i <= n; i++) if (num2str[i] != '\0') existChar[num2str[i] - 'a'] = true;
    for (int i = 0; i < wl[charNow]; i++) {
        if (!((num2str[senNum[w[numNow][0] + i]] == '\0' && !existChar[words[charNow][i] - 'a']) || num2str[senNum[w[numNow][0] + i]] == words[charNow][i])) return false;
    }
    return true;
    
}

bool isOK2() {
    int charNum[30];
    memset(charNum, 0, sizeof(charNum));
    for (int i = 1; i <= n; i++) if (num2str[i] != '\0') charNum[num2str[i] - 'a']++;
    for (int i = 0; i < 30; i++) if (charNum[i] > 1) return false;
    return true;
}

void DFS(int now) {
    if (now == wn) {
        for (int i = 0; i < 30; i++) ansNum2str[i] = num2str[i];
        answerNum++;
        return;
    }
    int nowLength = w[now][1] - w[now][0] + 1;
    for (int i = 0; i < q; i++) {
        if (wl[i] == nowLength && isOK(now, i)) {
            char lastNum2str[30];
            for (int j = 1; j <= n; j++) lastNum2str[j] = num2str[j];
            for (int j = 0; j < wl[i]; j++) num2str[senNum[w[now][0] + j]] = words[i][j];
            if (!isOK2()) {
                for (int j = 1; j <= n; j++) num2str[j] = lastNum2str[j];
                continue;
            }
            DFS(now + 1);
            for (int j = 1; j <= n; j++) num2str[j] = lastNum2str[j];
        }
    }
}

int main() {

    int caseNum;
    scanf("%d", &caseNum);
    while (caseNum--) {
        scanf("%d%d", &n, &m);
        for (int i = 0; i < m; i++) scanf("%d", senNum + i);
        scanf("%d", &q);
        memset(wordLength, false, sizeof(wordLength));
        for (int i = 0; i < q; i++) {
            scanf("%s", words[i]);
            wl[i] = strlen(words[i]);
            wordLength[wl[i]] = true;
        }

        answerNum = 0;

        for (int i = 1; i <= n; i++) {
            deli = i;
            if (check()) {
                memset(num2str, 0, sizeof(num2str));
                anAns = false;
                DFS(0);
                if (answerNum >= 2) break;
            }
        }

        if(answerNum == 0) printf("No solution\n");
        else if (answerNum >= 2) printf("Cannot determine\n");
        else {
            for (int i = 0; i < m; i++) {
                if (ansNum2str[senNum[i]] == '\0') printf(" ");
                else printf("%c", ansNum2str[senNum[i]]);
            }
            printf("\n");
        }

    }
    return 0;
}                                 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值