Katkat

Validate a Bijective Substitution Cipher

RemitlySoftware Engineer · Onsite

Last updated

Determine whether two printable ASCII strings form a valid one-to-one and onto (bijective) character substitution mapping.

Validate a Bijective Substitution Cipher

A substitution cipher replaces every occurrence of each character in an alphabet with another character. A substitution cipher is strictly bijective (one-to-one and onto) between two strings s1 and s2 if and only if:

  1. Both strings have the exact same length.
  2. Every character c in s1 maps consistently to the same corresponding character in s2 across all occurrences.
  3. No two distinct characters in s1 map to the same character in s2.

Given two strings s1 and s2 consisting of printable ASCII characters (including letters, digits, spaces, and punctuation), write a function to determine if s1 and s2 define a valid bijective substitution cipher.

Function Signature

def is_bijective_cipher(s1: str, s2: str) -> bool:
    pass

Constraints

  • 0 <= len(s1), len(s2) <= 10^5
  • s1 and s2 contain only printable ASCII characters (ASCII codes 32 to 126 inclusive).
  • Characters are case-sensitive ('A' and 'a' are distinct).

Examples

Example 1:

Input: s1 = "paper", s2 = "title"
Output: True
Explanation:
'p' -> 't'
'a' -> 'i'
'e' -> 'l'
'r' -> 'e'
Every character in s1 maps to a unique character in s2 consistently.

Example 2:

Input: s1 = "foo", s2 = "bar"
Output: False
Explanation:
'o' in s1 would need to map to both 'a' and 'r' in s2, which violates consistency.

Example 3:

Input: s1 = "ab", s2 = "aa"
Output: False
Explanation:
Both 'a' and 'b' map to 'a', violating the one-to-one requirement (collision).

Example 4:

Input: s1 = "Send $100!", s2 = "Wfoe %211?"
Output: True
Explanation:
Every character including spaces and symbols maps bijectively:
'S'->'W', 'e'->'f', 'n'->'o', 'd'->'e', ' '->' ', '$'->'%', '1'->'2', '0'->'1', '!'->'?'

Edge Cases to Consider

  • Mismatched lengths: Immediately invalid.
  • Empty strings: Two empty strings should return True.
  • Fixed-points: A character mapping to itself (e.g., ' ' -> ' ') is valid as long as no other character also maps to ' '.

Hints

Hint 1

Check if the lengths are equal first; if they differ, a bijection is impossible.

Hint 2

A mapping from s1 to s2 is not enough; you must also guarantee that two different characters in s1 do not map to the same character in s2.

Hint 3

Since the alphabet is limited to printable ASCII characters (95 distinct characters), you can track mappings using two arrays or hash maps in O(1) auxiliary space.

Follow-up questions

  • How would you modify your solution if characters are strictly forbidden from mapping to themselves (derangement)?
  • How would you reconstruct and return the cipher dictionary itself, and what should you do if an input string contains characters not in the mapped alphabet?
  • If s1 and s2 are read as infinite streams or chunked files that do not fit in memory, how would you validate the bijection on the fly?