1 条题解

  • 0
    @ 2026-4-2 23:38:42

    题目详细题解

    问题理解

    题目要求判断一个字符串 ss 是否与一个整数数组 aa(模板)匹配。匹配的条件本质上是要求字符串中的字符与数组中的数值之间建立一一对应的关系:

    • 相同的数值必须对应相同的字符
    • 相同的字符必须对应相同的数值

    这是一个典型的双射(bijection)问题。

    解题思路

    要验证这种一一对应关系,我们可以使用两个哈希表(字典):

    • 字典 m1m_1:记录字符 sis_i 对应哪个数值 aia_i
    • 字典 m2m_2:记录数值 aia_i 对应哪个字符 sis_i

    核心思想:同时维护两个方向的映射关系,确保每个字符唯一映射到一个数值,每个数值也唯一映射到一个字符。

    算法步骤

    1. 长度检查:如果 sn|s| \neq n,直接输出 "NO"

    2. 遍历检查:对于每个位置 jj0j<n0 \le j < n):

      • 取出当前字符 sjs_j 和当前数值 aja_j

      • 情况一:字符 sjs_j 和数值 aja_j 都尚未建立映射

        • 建立双向映射:m1[sj]=ajm_1[s_j] = a_jm2[aj]=sjm_2[a_j] = s_j
      • 情况二:已有映射但出现冲突

        • 如果 sjs_j 已经映射到某个数值,但该数值不是 aja_j,则冲突
        • 如果 aja_j 已经映射到某个字符,但该字符不是 sjs_j,则冲突
        • 出现任何冲突,则答案为 "NO"
    3. 完成遍历:如果没有冲突,则答案为 "YES"

    示例分析

    以示例中的第一个测试用例为例:

    a=[3,5,2,1,3]a = [3, 5, 2, 1, 3],检查字符串 "abfda"

    遍历过程:

    • j=0j=0s0=’a’s_0=\text{'a'}a0=3a_0=3 → 建立映射:’a’3\text{'a'}\to 33’a’3\to\text{'a'}
    • j=1j=1s1=’b’s_1=\text{'b'}a1=5a_1=5 → 建立映射:’b’5\text{'b'}\to 55’b’5\to\text{'b'}
    • j=2j=2s2=’f’s_2=\text{'f'}a2=2a_2=2 → 建立映射:’f’2\text{'f'}\to 22’f’2\to\text{'f'}
    • j=3j=3s3=’d’s_3=\text{'d'}a3=1a_3=1 → 建立映射:’d’1\text{'d'}\to 11’d’1\to\text{'d'}
    • j=4j=4s4=’a’s_4=\text{'a'}a4=3a_4=3 → 检查:’a’\text{'a'} 已映射到 3333 已映射到 ’a’\text{'a'},匹配 ✓

    输出 "YES"

    检查 "afbfa"

    • j=0j=0’a’3\text{'a'}\to 33’a’3\to\text{'a'}
    • j=1j=1’f’5\text{'f'}\to 55’f’5\to\text{'f'}
    • j=2j=2’b’2\text{'b'}\to 22’b’2\to\text{'b'}
    • j=3j=3s3=’f’s_3=\text{'f'}a3=1a_3=1 → 冲突:’f’\text{'f'} 已映射到 55,但当前位置数值是 11,不匹配 ✗

    输出 "NO"

    复杂度分析

    • 时间复杂度O(n+L)O(n + L),其中 LL 为所有字符串的总长度。每个字符串的每个字符只处理一次。
    • 空间复杂度O(min(n,26))O(\min(n, 26)),由于字符只有小写字母,映射表大小最多为 2626

    注意事项

    1. 数值 aia_i 的范围很大(109ai109-10^9 \le a_i \le 10^9),但数量有限,可以用字典存储。
    2. 字符集只有 2626 个小写字母,因此 m1m_1 最多有 2626 个键值对。
    3. 必须同时维护两个方向的映射,仅检查一个方向是不够的。
    4. 对于每个测试用例,处理每个字符串时都需要重新初始化两个空字典。

    代码实现要点

    def solve():
        n = int(input())
        a = list(map(int, input().split()))
        m = int(input())
        
        for _ in range(m):
            m1 = {}  # 字符 -> 数值
            m2 = {}  # 数值 -> 字符
            s = input().strip()
            
            if len(s) != n:
                print("NO")
                continue
            
            ok = True
            for j in range(n):
                if s[j] not in m1 and a[j] not in m2:
                    m1[s[j]] = a[j]
                    m2[a[j]] = s[j]
                elif (s[j] in m1 and m1[s[j]] != a[j]) or \
                     (a[j] in m2 and m2[a[j]] != s[j]):
                    ok = False
                    break
            
            print("YES" if ok else "NO")
    
    • 1

    信息

    ID
    6299
    时间
    1000ms
    内存
    256MiB
    难度
    3
    标签
    递交数
    2
    已通过
    1
    上传者