// 演算法 / Algorithm:
// 與 C 版相同：兩張查表記錄 s→t 與 t→s 的映射，單次掃描。
// 用陣列當查表（字元只有 256 種），比 unordered_map 更快更簡單。
// Same as C: two lookup tables for s→t and t→s, single pass.
// Arrays used as tables (only 256 possible chars) — faster/simpler than unordered_map.

#include <string>
#include <array>     // 提供固定大小陣列 std::array / fixed-size array container

class Solution {
public:
    bool isIsomorphic(std::string s, std::string t) {
        // std::array<int,256> 是固定大小陣列；{} 把每格初始化為 0
        // std::array<int,256> is a fixed-size array; {} zero-initializes every slot
        // 0 代表「尚未建立映射」(合法字元值 > 0) / 0 means "no mapping yet" (valid chars are > 0)
        std::array<int, 256> mapST{};   // s 字元 -> t 字元 / s-char -> t-char
        std::array<int, 256> mapTS{};   // t 字元 -> s 字元 / t-char -> s-char

        // range-for 取不到索引，這裡需要 i 同時索引 s 和 t，所以用傳統 for
        // a plain for loop because we need index i into both s and t at once
        for (std::size_t i = 0; i < s.size(); ++i) {
            // 轉成 unsigned char 再當索引，避免負值字元造成越界
            // cast to unsigned char before indexing, so high-bit chars don't go negative
            unsigned char a = static_cast<unsigned char>(s[i]);   // s 端字元 / char from s
            unsigned char b = static_cast<unsigned char>(t[i]);   // t 端字元 / char from t

            if (mapST[a] == 0 && mapTS[b] == 0) {
                // 第一次見到 -> 建立雙向映射 / first time seen -> set both directions
                mapST[a] = b;
                mapTS[b] = a;
            } else if (mapST[a] != b || mapTS[b] != a) {
                // 與既有映射矛盾 -> 不同構 / disagrees with existing mapping -> not isomorphic
                return false;
            }
            // 兩方向皆已存在且一致 -> 略過 / both exist and agree -> skip
        }

        // 全程無矛盾 -> 同構 / no conflict -> isomorphic
        return true;
    }
};
