이 문제에서는 하나의 문자열이 주어졌을 때, 폴리비우스 제곱 암호(Polybius Square Cipher)를 이용해 이를 숫자 형태로 암호화하는 방법을 다룹니다.
폴리비우스 제곱 암호란?
폴리비우스 제곱 암호는 문자를 숫자로 변환하기 위해 사용되는 표 기반 암호 기법입니다. 영어 암호화용 표는 5×5 크기로, 총 25개의 칸에 알파벳 26자를 배치합니다. 이때 I와 J는 하나의 칸에 함께 넣어 처리합니다.
다음 표는 폴리비우스 제곱 암호의 기본 형태입니다 −
| 1 | 2 | 3 | 4 | 5 | |
| 1 | A | B | C | D | E |
| 2 | F | G | H | I, J | K |
| 3 | L | M | N | O | P |
| 4 | Q | R | S | T | U |
| 5 | V | W | X | Y | Z |
표 안의 글자 배치는 무작위로 섞을 수 있으며, 사용 언어의 알파벳 개수에 따라 표의 크기 역시 유동적으로 조정할 수 있습니다.
각 알파벳은 표에서 고유한 좌표(행, 열)를 가집니다. 예를 들어 A는 1행 1열이므로 11로, H는 2행 3열이므로 23으로 변환됩니다. 이처럼 각 문자를 두 자리 숫자 쌍으로 치환하는 것이 폴리비우스 제곱 암호의 핵심 원리입니다.
예제로 이해하기
문제를 더 명확히 이해하기 위해 예를 살펴보겠습니다.
입력 − Hello
출력 − 2315313134
Hello를 좌표로 분해하면 H(2,3), E(1,5), L(3,1), L(3,1), O(3,4)가 되고, 이를 이어 붙여 2315313134라는 최종 숫자열이 완성됩니다.
접근 방법
이 문제를 해결하려면 문자열의 각 문자를 차례로 검사하면서, 해당 문자의 행(Row)과 열(Column) 값을 계산한 뒤 두 자리 숫자로 출력하는 프로그램을 작성하면 됩니다. 단, I와 J가 같은 칸을 공유하기 때문에 'j' 이후의 문자들에 대해서는 열 번호를 보정해 주는 추가 처리가 필요합니다.
C++ 구현 예제
아래 프로그램은 위에서 설명한 해결 방법을 실제로 구현한 것입니다 −
#include <cmath>
#include <iostream>
using namespace std;
void LetterToNumber(string str) {
int R, C;
for (int i = 0; str[i]; i++) {
R = ceil((str[i] - 'a') / 5) + 1;
C = ((str[i] - 'a') % 5) + 1;
if (str[i] == 'k') {
R = R - 1;
C = 5 - C + 1;
}
else if (str[i] >= 'j') {
if (C == 1) {
C = 6;
R = R - 1;
}
C = C - 1;
}
cout<<R<<C;
}
cout << endl;
}
int main() {
string str = "tutorialspoint";
cout<<"The numeric encryption of string '"<<str<<"' is : ";
LetterToNumber(str);
return 0;
}
코드 동작 원리
- 행 계산: R = ((str[i] - 'a') / 5) + 1 식으로 문자의 행 위치를 구합니다.
- 열 계산: C = ((str[i] - 'a') % 5) + 1 식으로 문자의 열 위치를 구합니다.
- I/J 예외 처리: 'k' 및 'j' 이후의 문자는 I·J가 같은 칸을 공유하는 특성 때문에 행·열 값을 별도로 보정합니다.
- 이 프로그램은 소문자 알파벳 입력을 기준으로 동작합니다.
출력 결과
The numeric encryption of string 'tutorialspoint' is: 4445443442241131433534243344
이 알고리즘은 문자열을 한 번만 순회하므로 시간 복잡도가 O(n)(n은 문자열 길이)으로, 매우 효율적으로 동작합니다.