題目:有一些單詞都成的字典,還有一些加密過的單詞組成的句子(除字母只有空格和換行);
求出一種可行的解碼方案(字母鍵間構成雙射),沒有解全都輸出*。
分析:搜索、回溯、dfs。對應每個句子中的單詞在字典里搜索對應的匹配項。
利用回溯法搜索,每次在整個字典中尋找匹配項,如果矛盾則返回;
矛盾:對應字母映射不同,或被映射的字母已經被別的字母映射到;
說明:有是好久沒做題了:-(。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char dict_word[1001][20];
int dict_word_length[1001];
char line_word[81][20];
int line_word_length[81];
char maps[128];
int search(int index, int line_size, int dict_size)
{
if (index >= line_size) {
return 1;
}
char save[128];
for (int c = 0; c <= 'z'; ++ c) {
save[c] = maps[c];
}
for (int i = 0; i < dict_size; ++ i) {
if (line_word_length[index] == dict_word_length[i]) {
int flag = 1;
for (int j = 0; j < line_word_length[index]; ++ j) {
if (!maps[line_word[index][j]] && !maps[dict_word[i][j]-'a']) {
maps[line_word[index][j]] = dict_word[i][j];
maps[dict_word[i][j]-'a'] = 1;
}else if (maps[line_word[index][j]] == dict_word[i][j]) {
continue;
}else {
flag = 0;
break;
}
}
if (flag && search(index+1, line_size, dict_size)) {
return 1;
}
for (int c = 0; c <= 'z'; ++ c) {
maps[c] = save[c];
}
}
}
return 0;
}
int main()
{
int n;
char lines[81];
scanf("%d",&n);
for (int i = 0; i < n; ++ i) {
scanf("%s",dict_word[i]);
dict_word_length[i] = strlen(dict_word[i]);
}
getchar();
while (gets(lines)) {
memset(maps, 0, sizeof(maps));
int count = 0, word_index = 0;
for (int i = 0; lines[i]; ++ i) {
if (lines[i] >= 'a' && lines[i] <= 'z') {
line_word[word_index][count ++] = lines[i];
}else {
line_word[word_index][count] = 0;
if (count > 0) {
line_word_length[word_index] = count;
word_index ++;
count = 0;
}
}
}
if (count > 0) {
line_word_length[word_index] = count;
word_index ++;
}
int flag = search(0, word_index, n);
for (int i = 0; lines[i]; ++ i) {
if (lines[i] >= 'a' && lines[i] <= 'z') {
if (flag) {
printf("%c",maps[lines[i]]);
}else {
printf("*");
}
}else {
printf(" ");
}
}
puts("");
}
return 0;
}