Редакция для Шифр простой замены по таблице
Submitting an official solution before solving the problem yourself is a bannable offence.
1. Идея
Дана таблица шифрования: для каждой буквы обычного алфавита известно, в какую букву она превращается.
Но требуется не зашифровать, а расшифровать текст. Значит, нужно построить обратное соответствие:
- если при шифровании
A -> Q, - то при расшифровке должно быть
Q -> A.
После этого остаётся пройти по всему шифротексту:
- если символ — заглавная латинская буква, заменяем её по обратной таблице;
- если это не буква, оставляем как есть.
2. Наблюдения
Таблица замены — это перестановка из 26 заглавных букв.
Значит, каждая буква встречается в ней ровно один раз, и обратная таблица тоже будет определена однозначно.Прямая таблица говорит:
- буква с индексом
iв обычном алфавите переходит вcipher_alphabet[i].
- буква с индексом
Для расшифровки удобнее хранить именно обратную таблицу:
- если
cipher_alphabet[i] = X, тоXдолжен расшифровываться в букву'A' + i.
- если
Пробелы и любые другие не-буквы менять не нужно.
В условии шифротекст состоит из заглавных букв и пробелов, но проверка на диапазон'A'..'Z'всё равно делает решение надёжным и понятным.
3. Алгоритм
- Считать строку
cipher_alphabet. - Считать строку
text. - Создать массив
revразмера 26, где:rev[k]— это буква исходного текста, которая соответствует зашифрованной букве с индексомk.
- Для каждого
iот0до25:- пусть
cipher_alphabet[i]— буква, в которую шифруется'A' + i; - тогда записываем:
rev[cipher_alphabet[i] - 'A'] = 'A' + i.
- пусть
- Пройти по всем символам строки
text:- если символ — буква от
AдоZ, добавить в ответrev[c - 'A']; - иначе добавить сам символ без изменений.
- если символ — буква от
- Вывести полученную строку.
4. Почему это работает
Докажем, что алгоритм действительно восстанавливает исходный текст.
Пусть некоторая исходная буква равна 'A' + i. По таблице шифрования она превращается в cipher_alphabet[i].
При построении массива rev мы записываем:
- для буквы
cipher_alphabet[i]обратное значение равно'A' + i.
Значит, если в шифротексте встречается буква cipher_alphabet[i], то при расшифровке мы получим ровно 'A' + i, то есть исходную букву.
Так работает для каждой из 26 букв, потому что таблица замены является перестановкой и все соответствия уникальны.
Для символов, которые не являются заглавными латинскими буквами, по условию нужно ничего не менять. Алгоритм именно так и делает.
Следовательно, каждая буква расшифровывается правильно, а остальные символы сохраняются. Значит, весь текст восстанавливается корректно.
5. Сложность
Построение обратной таблицы занимает O(26), то есть константное время.
Обработка текста длины n занимает O(n).
Итоговая сложность:
- по времени:
O(n); - по памяти:
O(26)помимо ответа, то естьO(1).
6. Код на C++17
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
string cipher_alphabet;
string text;
cin >> cipher_alphabet;
cin.ignore();
getline(cin, text);
vector<char> rev(26);
for (int i = 0; i < 26; i++) {
rev[cipher_alphabet[i] - 'A'] = char('A' + i);
}
string result;
for (char c : text) {
if (c >= 'A' && c <= 'Z') {
result += rev[c - 'A'];
} else {
result += c;
}
}
cout << result << '\n';
return 0;
}
7. Код на Python 3
cipher_alphabet = input()
text = input()
rev = [''] * 26
for i in range(26):
rev[ord(cipher_alphabet[i]) - ord('A')] = chr(ord('A') + i)
result = []
for c in text:
if 'A' <= c <= 'Z':
result.append(rev[ord(c) - ord('A')])
else:
result.append(c)
print(''.join(result))
Комментарии