【CCF 201903-3】损坏的RAID5

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";
    }
}
发布了91 篇原创文章 · 获赞 142 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/leelitian3/article/details/104142264
今日推荐