RAID5,对于学过操作系统的同学来说应该是比较熟悉的;如何根据块数确定该块所在的磁盘号和偏移量,是本题的难点。
本题踩到的一些坑
1. 关于输入的问题
int num = 0;
for (int i = 0; i < l; ++i)
{
// cin >> num >> disk[num]; 错误的写法
cin >> num;
cin >> disk[num];
}
2. 关于输出"-"的情况
我们在什么时候才能获得正确的磁盘数据呢?
毫无疑问,我们首先要保证请求的block编号是小于等于最大block编号的;
当 l = n 时,我们知道所有磁盘的数据;(√)
当 l = n - 1 时,我们可以根据剩下的 n - 1 块磁盘求异或和,来得出剩下的一个磁盘; (√)
当 l < n - 1 时,如果我们所求的block正好在我们已知数据的硬盘上,那么也是可以的; (√)
C++11满分代码
#include <cstring>
#include <iostream>
#include <sstream>
#include <unordered_map>
#include <vector>
using namespace std;
int n, s, l, m;
vector<string> disk;
unordered_map<char, int> char2int; // 十六进制字符转int
unordered_map<int, char> int2char;
// 16进制字符串异或
void string_xor(string &a, string b)
{
for (size_t i = 0; i < a.length(); ++i)
a[i] = int2char[char2int[a[i]] ^ char2int[b[i]]];
}
// 初始化两个哈希表
void init_map()
{
for (int i = 0; i < 10; ++i)
{
int2char[i] = i + '0';
char2int[i + '0'] = i;
}
for (int i = 10; i < 16; ++i)
{
int2char[i] = i + 'A' - 10;
char2int[i + 'A' - 10] = i;
}
}
int main()
{
// 关闭同步
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
init_map();
cin >> n >> s >> l;
disk.assign(n, string());
int num = 0;
for (int i = 0; i < l; ++i)
{
cin >> num;
cin >> disk[num];
}
// 最大块的编号
int max_block = (n - 1) * disk[num].length() / 8;
int block = 0;
cin >> m;
while (m--)
{
cin >> block;
// 输出为"-"的情况
if (block >= max_block)
{
cout << "-\n";
continue;
}
int row = block / (s * (n - 1));
int disk_p = n - 1 - (row % n);
int disk_num = (disk_p + ((block % (s * (n - 1))) + s) / s) % n;
int begin = (row * s + block % s) * 8; // 字符串的开始位置
// 如果我们已知该硬盘的数据
if (!disk[disk_num].empty())
cout << disk[disk_num].substr(begin, 8) << "\n";
// 如果此硬盘数据未知,则需要根据剩下的所有数据求异或和
else if(l == n - 1)
{
string res(8, '0');
for (int i = 0; i < n; ++i)
{
if (i != disk_num)
string_xor(res, disk[i].substr(begin, 8));
}
cout << res << "\n";
}
else
cout << "-\n";
}
}