UVa 828 - Deciphering Messages

contents

  1. 1. Problem
  2. 2. Sample Input
  3. 3. Sample Output
  4. 4. Solution

Problem

給一加密原則,現在要求解密,並且在只有一組文本情況下輸出正解。

一開始給定一字串 L,接著加密時,每一組訊息的 word,由左而右加密。

  • 如果字符 c 存在於 L,使用凱薩加密 shift N 位。
  • 如果字符 c 不存在於 L,輸出三個字浮,分別是 L[m]、c 使用凱薩加密 shift N 位、L[m+1]。每一次使用這一條 m 就 +1,假想 L 是環狀的。

Sample Input

1
2
3
4
5
6
7
8
9
10
1
RSAEIO
2
5
RTSSKAEAGE
GRSCAV
RGSSCAV
RUSIQO
RUSSGAACEV JEGIITOOGR

Sample Output

1
2
3
4
5
RICE
error in encryption
EAT
error in encryption
SEAT HERE

Solution

搜索,雖然看起來有點可怕,但是條件很多,如果搜索到兩種以上的情況,立即退出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sstream>
using namespace std;
int inL[128] = {}, N, Q, Llen;
char L[128], s[1024];
char text[128];
int sol;
void dfs(int idx, int pl, int m) {
while (s[idx] == ' ') text[pl++] = ' ', idx++;
if (sol >= 2) return;
if (s[idx] == '\0') {
sol++;
text[pl] = '\0';
puts(text);
return;
}
char a, b, c;
for (int i = 'A'; i <= 'Z'; i++) {
if (inL[i]) {
a = L[m%Llen];
b = (i-'A'+N)%26 + 'A';
c = L[(m+1)%Llen];
text[pl] = i;
if (a == s[idx] && b == s[idx+1] && c == s[idx+2]) {
dfs(idx+3, pl+1, m+1);
}
} else {
a = (i-'A'+N)%26 + 'A';
text[pl] = i;
if (a == s[idx]) {
dfs(idx+1, pl+1, m);
}
}
}
}
int main() {
int testcase;
scanf("%d", &testcase);
while (testcase--) {
scanf("%s", L);
scanf("%d %d", &N, &Q);
memset(inL, 0, sizeof(inL));
for (int i = 0; L[i]; i++)
inL[L[i]] = 1;
Llen = strlen(L);
while (getchar() != '\n');
for (int i = 0; i < Q; i++) {
gets(s);
sol = 0;
dfs(0, 0, 0);
if (sol != 1)
puts("error in encryption");
}
if (testcase)
puts("");
}
return 0;
}