일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 독후감
- 정보영재원
- 배열
- 프로그래밍
- 정보과학
- 문제출저:www.dovelet.com
- 제어문
- 반복문
- 영재교육원
- 수학영재원
- 백도어
- API
- Backdoor
- 풀이&소스코드저작권:왕유승
- C
- C++
- 참조은요양병원
- 독서 감상문
- 정보올림피아드
- For문
- Linux
- if문
- DBMS
- c언어
- 자료구조
- 알고리즘
- 리눅스
- IT
- 리눅스 명령어
- 다중반복문
- Today
- Total
되는대로 살자
[C언어 기출문제&풀이] Crypt Kicker 본문
문제: 텥ㄱ스트를 암호화하는 방법 중에 보안상 취약하긴 하지만 흔하게 쓰이는 방법으로 알파벳 글자를 다른 글자로 돌리는 방법이 있다. 즉 알파벳의 각 글자를 다른 글자로 치환하낟. 암호화된 것을 닷 원래대로 되돌릴 수 있으려면 두 개의 서로 다른 글자가 같은 글자로 치환되지 않아야 한다.
암호화된 텍스트가 한 줄 이상 입력되는데, 각 줄마다 서로 다른 치환 방법이 적용된다고 가정하자.
암호화 이전의 텍스트에 있는 단어는 모두 주어진 사전에 들어있는 단어라고 가정하고, 암호화된 텍스트를 해독하여 원래 텍스트를 알아내자.
임력: 입력은 한 개의 정수 n이 들어있는 행으로 시작되며 그 다음 줄부터는 한 줄에 하나씩 n개의 소문자로 쓰인 단어들이 알파벳 순으로 입력된다. 이 n개의 단어들은 복호화된 텍스트에 들어갈 수 있는 단어로 구성된 사전이다. 사전 뒤에는 몇 줄의 텍스트가 입력된다. 각 줄은 앞에서 설명했던 방법에 따라 암호화된다.
사전에 들어갈 수 있는 단어읭 개수는 1000개를 넘지 않는다. 단어의 길이는 16글자를 넘지 않는다. 암호화된 텍스트에는 소문자와 스페이스만 들어가며 한 줄의 길이는 80 글자를 넘어가지 않는다.
출력: 각 줄을 복호화하여 표준 출력으로 출력한다. 여러 문장으로 복호화될 수 있다면 그 중 아무 결과나 출력하면 된다. 가능한 풀이가 없다면 알파벳 모든 문자를 아스테리스크로 바꾸면 된다.
문제 풀이: 입력받은 단어를 dic[]에 저장하고, 단어를 매치시켜본다 조건은 두가지가 만족되어야 하는데 1. 한 문자가 ㄷ서로 다른 두 문자로 매핑되어서는 안된다.
2. 서로 다른 두 문자가 같은 문자로 매핑될 수 없다.
소스코드
#include <stdio.h>
#include <string.h>
#define MAX_DIC_SIZE 1000
#define MAX_LINE_LENGTH 80
#define MAX_WORD_LENGTH 16
static char dic[MAX_DIC_SIZE][MAX_WORD_LENGTH +1];
static char line[MAX_LINE_LENGTH+1];
static unsigned int dic_size;
static unsigned int line_len;
int search(unsigned int k, char *map, char *inv)
{
char word[MAX_WORD_LENGTH +1];
char map2['z' + 1],inv2['z'+1];
unsigned int i,j,t;
char c;
while(line[k] == ' ')
k++;
if(k >= line_len)
{
for(i=0;i<line_len;i++)
putchar(line[i]==' '?' ': map[line[i]]);
putchar('\n');
return 1;
}
//k번째 위치 이후의 첫번째 단어를 찾아낸다.
for(t=0;line[k+t] >='a' && line[k+t] <= 'z';t++)
word[t] = line[k+t];
word[t] = '\0'; //단어가 끝나고 NULL 로 지정
for(i=0;i<dic_size;i++)
//사전에서 길이가 같은 단어를 검색
if(strlen(dic[i]) == t)
{
for(c='a'; c<='z';c++)
{
map2[c] = map[c]; //c번째 글자를 매핑
inv2[c] = inv[c]; // 역반환 저장
}
}
//word를 dic[i]에 일치시키면서, mapping의
//일관성이 유지되는지 검사
for(j=0;j<t;j++) // t=k번째 위치 이후의 첫번째 단어의 길이
{
//검사하고자하는 단어의 j번째 문자가 이미 기록되어 있고
// '' 가 이 단어와 매치가 되지 않을 때
if(map2[word[j]] && map2[word[j]] !=dic[i][j]
|| inv2[dic[i][j]] && inv2[dic[i][j]] != word[j])
goto end_of_loop_i;
else
{
map[word[j]] = dic[i][j];
inv2[dic[i][j]] = word[j];
}
if(search(k+t,map2, inv2))
return 1;
end_of_loop_i: ;
}
return 0;
}
int main()
{
char map['z'+1], inv['z'+1];
unsigned int i;
scanf("%d",&dic_size);
gets(line);
for(i=0;i<dic_size;i++)
gets(dic[i]);
while(gets(line) && *line !=EOF)
{
line_len = strlen(line);
for(i='a';i<='z';i++)
{
map[i] = '\0';
inv[i] = '\0';
}
if(!search(0,map,inv))
{
for(i=0;i<line_len;i++)
putchar(line[i] == ' ' ? ' ': '*');
putchar('\n');
}
}
}
'2009~2014 > C/C++' 카테고리의 다른 글
[C언어 기출문제&풀이] 두 수 (0) | 2011.07.21 |
---|---|
[C언어 기출문제&풀이] 제네레이터 (0) | 2011.07.02 |
[C언어 기출문제&풀이] 두 색으로 칠하기(Bicoloring) (2) | 2011.05.16 |
[C언어 기출문제&풀이] 쌓아 올리기(Stack 'em Up) (0) | 2011.05.15 |
[C언어 기출문제&풀이] 동맹휴업(Hartal) (0) | 2011.05.15 |