📜  门| GATE CS 2020 |第 44 题(1)

📅  最后修改于: 2023-12-03 15:28:38.493000             🧑  作者: Mango

GATE CS 2020 第44题

本题是一道关于计算机科学中图形学基础的问题。以下是问题及其解答。

问题描述

设一个 $3\times 3$ 的字符矩阵 $M$,其中所有字符都是大写字母。设一个点序列 $P$ 是按下述规则生成的:

  1. 由矩阵 $M$ 的中央的字符(即 $M_2$),出发向上行走 $m$ 步,再向左走 $n$ 步($1 \leq m,n \leq 9$)。如果向左走时无法继续前进,则终止此方向行动并改为在该方向旋转(左侧旋转 $90^\circ$)再继续。
  2. 按上述行动规律不断行动,直到回到矩阵中央字符位置。

对于一个长度为 $k$ 的字符串 $S$,定义 $M$ 上的一个子串 $STR$ 是匹配 $S$ 的一段连续的子序列,若将 $STR$ 上的字符按行顺序排列,所得的字符串与 $S$ 完全一致。

现在,你需要编写一个程序,对于每个输入的点序列 $P$,查询该点序列能够匹配给定的字符串 $S$ 中的哪些子串。

解答
思路分析

首先需要注意的是,题目所给的点序列可能是有环的。而如果照着题目所给的走法,最终一定会回到中央字符位置。

因此,可以将点序列看作是一个环,并计算出它的长度 $l$。之后可以将点序列按照起点处为 $1$ 的编号方式来标号,并使用模 $l$ 运算来计算它的下一个位置。

我们可以通过枚举所有子串的起点来判断这个子串是否与点序列 $P$ 相匹配。如果要匹配的子串是 $S$ 的子字符串,则对于 $S$ 的第 $i$ 个字符,我们可以计算出从点序列的当前位置出发,到达下一个与 $S_i$ 匹配的字符所需经过的步数。如果在按照这些步数行走后,点序列可以恰好回到中央字符位置,则说明该字符串与点序列 $P$ 相匹配。

代码实现

下面是本题的一份 Python 代码实现。

def match_string(P, S):
    # 将点序列看作是一个环,并计算出它的长度
    l = len(P)

    matches = []
    for i in range(len(S)):
        # 计算出从点序列的当前位置出发,到达下一个与 S[i] 匹配的字符所需经过的步数
        steps = []
        for j in range(l):
            step = 0
            while P[(j+step) % l] != S[i]:
                step += 1
            steps.append(step)

        # 判断是否匹配
        flag = True
        cur = 0
        for step in steps:
            cur += step
            if cur >= l:
                flag = False
                break
            cur %= l
        if flag and cur == 0:
            matches.append(i)

    return matches

本题的时间复杂度为 $O(|S|l^2)$,其中 $|S|$ 是 $S$ 的长度。