1 条题解
-
0
📝 题目大意
给定两个 行 列的网格 和 (由
#和.组成),判断是否可以通过对 的列进行重新排列,使其与 完全相同。💡 解题思路
-
题目分析:重新排列列意味着可以选择任意 的排列 ,将 的第 列移动到第 列。由于 可以是任意排列,本质上就是问: 的 列的多重集与 的 列的多重集是否相同。数据范围 ,保证了 的算法可行。
-
算法推导:
- 将每一列看作一个长度为 的字符串(由上到下拼接该列的所有字符)。
- 代码中用
cnt[0][j]存储 的第 列,cnt[1][j]存储 的第 列。 - 读入时逐行处理,将每个字符追加到对应列的字符串末尾,即实现了行列转置。
- 将 和 各自的 个列字符串分别排序。排序后,如果两个多重集相同,排序结果必然一一对应相等。
- 逐列比较排序后的结果,若全部相等则输出
Yes,否则输出No。
-
边界与细节:
- 或 的情况:算法仍然正确。当 时,只有一个列,排序后直接比较即可。
- 的情况:显然排序后全等,输出
Yes。 - 列字符串长度较大(),但总字符数不超过 ,排序比较的总开销可控。
- 注意数组下标从 开始,排序时使用
cnt[n] + 1到cnt[n] + w + 1。
⏱️ 复杂度分析
- 时间复杂度:。其中 是构建列字符串的开销, 是排序 个长度为 的字符串的比较开销。由于 ,总操作量在可接受范围内。
- 空间复杂度:,用于存储两套列字符串。
💻 标准代码 (C++)
#include <bits/stdc++.h> using namespace std; signed main() { int h, w; // cnt[0] 存储 S 的各列,cnt[1] 存储 T 的各列 string cnt[2][400010] = {}; cin >> h >> w; // n = 0 处理 S,n = 1 处理 T for (int n = 0; n <= 1; n++) for (int i = 1; i <= h; i++) { string s; cin >> s; // 将第 i 行的每个字符追加到对应列的字符串中,实现行列转置 for (int j = 1; j <= w; j++) cnt[n][j] += s[j - 1]; } // 对 S 和 T 的列字符串分别排序 for (int n = 0; n <= 1; n++) sort(cnt[n] + 1, cnt[n] + w + 1); // 逐列比较,若有不相等则说明两个多重集不同 for (int i = 1; i <= w; i++) if (cnt[0][i] != cnt[1][i]) { cout << "No"; return 0; } cout << "Yes"; return 0; } -
- 1
信息
- ID
- 661
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- (无)
- 递交数
- 1
- 已通过
- 1
- 上传者